暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 19C CURSOR_SHARING = FORCE时的解析行为

原创 Asher.HU 2021-02-04
2907


当SQL语句使用文字而不是绑定变量时,请设置CURSOR_SHARING初始化参数以FORCE使数据库能够将文字替换为系统生成的绑定变量。使用这种技术,数据库有时可以减少共享SQL区域中父游标的数量。

注意:

如果一条语句使用一个ORDER BY子句,则数据库不会在该子句中执行文字替换,因为将常量列号视为文字在语义上是不正确的。ORDER BY子句中的列号影响查询计划和执行,因此数据库不能共享两个具有不同列号的游标。


CURSOR_SHARING设置为时FORCE,数据库在解析期间执行以下步骤:

  1. 将语句中的所有文字复制到PGA,并用系统生成的绑定变量替换它们

    例如,一个应用程序可以处理以下语句:

    SELECT SUBSTR(last_name, 1, 4), SUM(salary) 
    FROM   hr.employees 
    WHERE  employee_id < 101 GROUP BY last_name

    优化器将替换文字,包括SUBSTR函数中的文字,如下所示:

    SELECT SUBSTR(last_name, :"SYS_B_0", :"SYS_B_1"), SUM(salary) 
    FROM   hr.employees 
    WHERE  employee_id < :"SYS_B_2" GROUP BY last_name
  2. 在共享池中搜索相同的语句(相同的SQL哈希值)

    如果相同的语句没有找到,则数据库执行硬分析。否则,数据库将继续进行下一步。

  3. 对语句执行软解析

由于前面的步骤表明,设置CURSOR_SHARING初始化参数FORCE没有减少解析数。而是,在某些情况下,FORCE使数据库能够执行软解析而不是硬解析。另外,FORCE也不能防止SQL注入攻击,因为Oracle数据库会在发生任何注入后绑定值。



示例20-11用系统绑定变量替换文字

本示例在会话级别设置CURSOR_SHARINGFORCE,执行三个包含文字的语句,并显示每个语句的计划:

ALTER SESSION SET CURSOR_SHARING=FORCE;
SET LINESIZE 170
SET PAGESIZE 0
SELECT SUM(salary) FROM hr.employees WHERE employee_id < 101;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
SELECT SUM(salary) FROM hr.employees WHERE employee_id < 120;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
SELECT SUM(salary) FROM hr.employees WHERE employee_id < 165;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());


DISPLAY_CURSOR为提高可读性而编辑的以下输出显示,所有三个语句都使用相同的计划。优化程序选择了计划,即索引范围扫描,因为它偷看了绑定到系统绑定变量第一个值(101),并选择了该计划作为所有值的最佳选择。   实际上,该计划并不是针对所有价值的最佳计划。当值为时165,全表扫描更有效。

SQL_ID	cxx8n1cxr9khn, child number 0
-------------------------------------
SELECT SUM(salary) FROM hr.employees WHERE employee_id < :"SYS_B_0"

Plan hash value: 2410354593

-------------------------------------------------------------------------------------
| Id  | Operation                           | Name       |Rows|Bytes|Cost(%CPU)|Time|
-------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT                     |               |  |   |2 (100)|        |
|  1 |  SORT AGGREGATE                      |               |1 | 8 |       |        |
|  2 |   TABLE ACCESS BY INDEX ROWID BATCHED| EMPLOYEES     |1 | 8 |2 (0)  |00:00:01|
|* 3 |    INDEX RANGE SCAN                  | EMP_EMP_ID_PK |1 |   |1 (0)  |00:00:01|
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("EMPLOYEE_ID"<101)

查询V$SQLAREA确认Oracle Database被具有系统绑定变量的文字替换:”SYS_B_0”,并VERSION_COUNT=1为所有三个语句创建了一个父级和一个子级游标(),这意味着所有执行都共享相同的计划。

COL SQL_TEXT FORMAT a36
SELECT SQL_TEXT, SQL_ID, VERSION_COUNT, HASH_VALUE
FROM   V$SQLAREA
WHERE  SQL_TEXT LIKE '%mployee%'
AND    SQL_TEXT NOT LIKE '%SQL_TEXT%';

SQL_TEXT                             SQL_ID        VERSION_COUNT HASH_VALUE
------------------------------------ ------------- ------------- ----------
SELECT SUM(salary) FROM hr.employees cxx8n1cxr9khn             1  997509652
 WHERE employee_id < :"SYS_B_0"

也可以看看:

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论