基于ORACLE SQL优化书读之cursor(2)
2021/4/15 19:58:05
本文主要是介绍基于ORACLE SQL优化书读之cursor(2),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
上篇文章主要介绍了关于cursor的一些实现和工作原理,以及关于父子cursor的存储方式等理论部分,接下来我们来进行一番实验来印证我们的理论。
如下为实验部分,在scott用户下进行查询emp表的数据:
SQL> select empno,ename from emp;
EMPNO ENAME
---------- --------------------
7369 SMITH
7499 ALLEN
...
7902 FORD
7934 MILLER
已选择 14 行。
SQL> select sql_text,sql_id,version_count from v$sqlarea where sql_text like 'select empno,ename%';
SQL_TEXT SQL_ID VERSION_COUNT
-------------------------------------------------- -------------------------- -------------
select empno,ename from emp 78bd3uh4a08av 1
SQL> select plan_hash_value,child_number from v$sql where sql_id='78bd3uh4a08av';
PLAN_HASH_VALUE CHILD_NUMBER
--------------- ------------
3956160932 0
注意原目标SQL在v$sqlarea中只有一条记录且version count为1,说明Oracle在执行SQL确实只产生一个parent cursor和child cursor,并且只产生了一个子游标号为0的child cursor。
SQL> select empno,ename from EMP;
EMPNO ENAME
---------- --------------------
7369 SMITH
7499 ALLEN
...
7900 JAMES
7902 FORD
7934 MILLER
已选择 14 行。
SQL> select sql_text,sql_id,version_count from v$sqlarea where sql_text like 'select empno,ename%';
SQL_TEXT SQL_ID VERSION_COUNT
-------------------------------------------------- -------------------------- -------------
select empno,ename from emp 78bd3uh4a08av 1
select empno,ename from EMP 53j2db788tnx9 1
SQL> select plan_hash_value,child_number from v$sql where sql_id='53j2db788tnx9';
PLAN_HASH_VALUE CHILD_NUMBER
--------------- ------------
3956160932 0
之后把表emp改写成大写的EMP,发现又产生了一条游标记录,很明显是由于hash运算得到的哈希值去hash bucket中找匹配的parent cursor,由于hash运算对大小写的敏感性,导致hash bucket很有可能不是同一个,即便是同一个由于parent cursor中的name所存储的值也明显不同--即不同的SQL语句,所以肯定会产生一对新的parent cursor和child cursor。
然后我们再换另外一个用户test来尝试一下查询同一条sql语句,步骤如下:
SQL> conn test/test@orclp
已连接。
SQL> create table emp as select * from scott.emp;
表已创建。
SQL>
SQL>
SQL> select empno,ename from emp;
EMPNO ENAME
---------- --------------------
7369 SMITH
7499 ALLEN
...
7902 FORD
7934 MILLER
已选择 14 行。
SQL> select sql_text,sql_id,version_count from v$sqlarea where sql_text like 'select empno,ename %';
SQL_TEXT SQL_ID VERSION_COUNT
-------------------------------------------------- -------------------------- -------------
select empno,ename from emp 78bd3uh4a08av 2
select empno,ename from EMP 53j2db788tnx9 1
SQL> select plan_hash_value,child_number from v$sql where sql_id='78bd3uh4a08av';
PLAN_HASH_VALUE CHILD_NUMBER
--------------- ------------
3956160932 0
3956160932 1
上述实验表明,当我们使用另外一个用户来进行相同的查询时,Oracle会根据目标SQL文本的哈希值来找相应的hash bucket中的parent cursor,然后遍历其child cursor,但是此时发现child cursor中的解析数和执行计划不能被重用,原因是child cursor中的解析数和执行计划是针对Scott用户下的emp表,而不是针对test用户下的。也就是目标表不是同一张表,这也就意味着Oracle要针对test用户下的emp表再次从头做一次解析,并将结果存入新生成的child cursor中,再挂到parent cursor下,也就是说该SQL对应的parent cursor中会有两个child cursor。上述实验也验证了这一点,child_number值分别为0和1。
如下我们来归纳一下关于sql解析是如何在buffer cache中寻找cursor的过程:
依次顺序执行如下步骤:
1)、根据目标SQL的SQL文本的hash 值去库缓存中找匹配的hash bucket,更准确的说是基于对应库缓存对象句柄属性name和namespace的值的;
2)、然后在匹配的hash bucket库缓存对象链表中查找匹配的parent cursor,当然,在查找匹配parent cursor的过程中肯定会比对目标的SQL的SQL文本(因为不同的SQL文本计算出来的hash 值可能相同)
3)、步骤2如果找到匹配的parent cursor,则Oracle接下来就会遍历从属于该parent cursor的所有child cursor查找匹配的child cursor。
4)、如果找不到匹配的parent cursor,就表明没有共享的解析数和执行计划,Oracle会从头解析SQL,新生成的parent cursor和一个child cursor,并把它们挂在对应的hash bucket中。
5)、步骤3如果找到匹配的child cursor,则Oracle会把存储于该child cursor中的解析数和执行计划直接拿过来重用。
6)、步骤3如果找不到匹配的child cursor,则表明没有可以共享的解析树和执行计划,Oracle会从头解析SQL。
这篇关于基于ORACLE SQL优化书读之cursor(2)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-06PingCAP 连续两年入选 Gartner 云数据库管理系统魔力象限“荣誉提及”
- 2025-01-05Easysearch 可搜索快照功能,看这篇就够了
- 2025-01-04BOT+EPC模式在基础设施项目中的应用与优势
- 2025-01-03用LangChain构建会检索和搜索的智能聊天机器人指南
- 2025-01-03图像文字理解,OCR、大模型还是多模态模型?PalliGema2在QLoRA技术上的微调与应用
- 2025-01-03混合搜索:用LanceDB实现语义和关键词结合的搜索技术(应用于实际项目)
- 2025-01-03停止思考数据管道,开始构建数据平台:介绍Analytics Engineering Framework
- 2025-01-03如果 Azure-Samples/aks-store-demo 使用了 Score 会怎样?
- 2025-01-03Apache Flink概述:实时数据处理的利器
- 2025-01-01使用 SVN合并操作时,怎么解决冲突的情况?-icode9专业技术文章分享