【DB笔试面试586】在Oracle中,什么是自适应游标共享(2)?

  • 2019 年 10 月 10 日
  • 筆記

另外,在目标列有Frequency类型直方图的前提条件下,如果对目标列施加等值查询条件,且该查询条件的输入值等于该列的某个实际值时,则该谓词条件的可选择率的计算公式为如下所示:

selectivity=BucketSize/NUM_ROWS

其中,BucketSize表示目标列的某个实际值所对应的记录数。

合并上述计算公式可以得出,对于表TI而言,在当前情形下V$SQL_CS_SELECTIVITY中记录的可选择率的范围的计算公式为[0.9*BucketSize/NUM_ROWS,1.1*BucketSize/NUM_ROWS]。

对于上述CHILD NUMBER为1的Child Cursor而言,绑定变量攴的输入值为“TABLE”时对应的记录数为61818(即BucketSize的值是61818),表Tl的记录数为78174(即NUM_ROWS的值为78174),将61818和78174带入上述合并后的计算公式:

LHR@orclasm > SELECT d.NUM_ROWS FROM dba_tables d WHERE d.TABLE_NAME='T_ACS_20170611_LHR';      NUM_ROWS  ----------       78174  LHR@orclasm > SELECT ROUND(0.9*(61818/78174),6) low,ROUND(1.1*(61818/78174),6) HIGH FROM DUAL;           LOW       HIGH  ---------- ----------    0.711697    0.869852    --从上述计算结果可以看出,可选择率范围和之前从VSSQL_CS_SELECTIVITY中查到的结果完全一致。  --现在将X的值修改为“INDEX”:  LHR@orclasm > EXEC :X :='INDEX';    PL/SQL procedure successfully completed.    LHR@orclasm > SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=:X;      COUNT(*)  ----------        3082    LHR@orclasm >  LHR@orclasm > SELECT A.SQL_TEXT, A.SQL_ID,A.VERSION_COUNT,A.EXECUTIONS FROM V$SQLAREA A WHERE A.SQL_TEXT LIKE 'SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=%';    SQL_TEXT                                                                                 SQL_ID        VERSION_COUNT EXECUTIONS  ---------------------------------------------------------------------------------------- ------------- ------------- ----------  SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=:X                         bt8tk3f1tnwcf             3          4  LHR@orclasm > SELECT A.SQL_ID,A.CHILD_NUMBER,A.EXECUTIONS,A.BUFFER_GETS,A.IS_BIND_SENSITIVE,A.IS_BIND_AWARE,A.IS_SHAREABLE,A.PLAN_HASH_VALUE FROM V$SQL A WHERE A.SQL_ID='bt8tk3f1tnwcf';    SQL_ID        CHILD_NUMBER EXECUTIONS BUFFER_GETS I I I PLAN_HASH_VALUE  ------------- ------------ ---------- ----------- - - - ---------------  bt8tk3f1tnwcf            0          2         309 Y N N      3002671579  bt8tk3f1tnwcf            1          1         522 Y Y Y      4256744017  bt8tk3f1tnwcf            2          1          16 Y Y Y      3002671579    LHR@orclasm >  

从如下查询结果可以看到,目标SQL对应的列VERSION_COUNT的值从之前的2变为现在的3,列EXECUTIONS的值为4,说明Oracle在第4次执行该SQL时依然用的是硬解析。目标SQL多了一个CHILD_NUMBER为2的新Child Cursor,且该Child Cursor对应的IS_BIND_SENSITIVE、IS_BIND_AWARE和IS_SHAREABLE的值均为Y,但是这个新Child Cursor和CHILD_NUMBER为0的原有Child Cursor的对应PLAN_HASH_VALUE的值均为3002671579(说明这两个Child Cursor中存储的执行计划是相同的),而且CHILD_NUMBER为0的原有Child Cursor对应IS_SHAREABLE的值己经从之前的Y变为现在的N。

这些变化表明,对于标记为Bind Aware的Child Cursor所对应的目标SQL,当该SQL后续再次被执行时如果对应的是硬解析,且本次硬解析所产生的执行计划和原有Child Cursor中存储的执行计划相同,则Oracle此时除了会新生成一个Child Cursor之外,还会把存储相同执行计划的原有Child Cursor标记为非共享(把原有Child Cursor在V$SQL中对应记录的列IS SHAREABLE的值从Y改为N)。

目标SQL现在的执行计划如下所示:

LHR@orclasm > SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('bt8tk3f1tnwcf',2,'advanced'));    PLAN_TABLE_OUTPUT  ---------------------------------------------------------------------------------------  SQL_ID  bt8tk3f1tnwcf, child number 2  -------------------------------------  SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=:X    Plan hash value: 3002671579    ---------------------------------------------------------------------------------------  | Id  | Operation         | Name              | Rows  | Bytes | Cost (%CPU)| Time     |  ---------------------------------------------------------------------------------------  |   0 | SELECT STATEMENT  |                   |       |       |    15 (100)|          |  |   1 |  SORT AGGREGATE   |                   |     1 |     7 |            |          |  |*  2 |   INDEX RANGE SCAN| IDX_ACS_OBJID_LHR |  3082 | 21574 |    15   (0)| 00:00:01 |  ---------------------------------------------------------------------------------------    Query Block Name / Object Alias (identified by operation id):  -------------------------------------------------------------       1 - SEL$1     2 - SEL$1 / T@SEL$1    Outline Data  -------------      /*+        BEGIN_OUTLINE_DATA        IGNORE_OPTIM_EMBEDDED_HINTS        OPTIMIZER_FEATURES_ENABLE('11.2.0.3')        DB_VERSION('11.2.0.3')        ALL_ROWS        OUTLINE_LEAF(@"SEL$1")        INDEX(@"SEL$1" "T"@"SEL$1" ("T_ACS_20170611_LHR"."OBJECT_TYPE"))        END_OUTLINE_DATA    */    Peeked Binds (identified by position):  --------------------------------------       1 - :X (VARCHAR2(30), CSID=852): 'INDEX'    Predicate Information (identified by operation id):  ---------------------------------------------------       2 - access("T"."OBJECT_TYPE"=:X)    Column Projection Information (identified by operation id):  -----------------------------------------------------------       1 - (#keys=0) COUNT(*)[22]      49 rows selected.  

从上述显示内容可以看出,目标SQL现在的执行计划是走对索引IDX_ACS_OBJID_LHR的索引范围扫描,确实与CHILD_NUMBER为0的原有Child Cursor中存储的执行计划相同。注意到“Peeked Binds”部分的内容为“1 – :X (VARCHAR2(30), CSID=852): 'INDEX'”,这说明Oracle在硬解析目标SQL的过程中确实再次使用了绑定变量窥探,而且做“窥探”这个动作时看到的绑定变量的输入值为“INDEX”。

现在的问题是,既然Oracle此时选择的执行计划与原有Child Cursor中存储的执行计划相同,为什么不直接沿用原先的执行计划而是还得再做一次硬解析呢?

在介绍自适应游标共享的整体执行流程时曾经提到过:对于标记为Bind Aware的Child Cursor所对应的目标SQL,当该SQL再次被执行时,Oracle就会根据当前传入的绑定变量值所对应的谓词条件的可选择率,来决定该SQL此时的执行是用硬解析还是用软解析/软软解析。

对于上述CHILD_NUMBER为2的Child Cursor,绑定变量攴的输入值为“INDEX”时对应的记录数为3082,表TI的记录数为78174,带入合并后的计算公式:

LHR@orclasm > SELECT ROUND(0.9*(3082/78174),6) low,ROUND(1.1*(3082/78174),6) HIGH FROM DUAL;           LOW       HIGH  ---------- ----------    0.035482    0.043367  LHR@orclasm > SELECT * FROM V$SQL_CS_SELECTIVITY D WHERE D.SQL_ID='bt8tk3f1tnwcf' ORDER BY CHILD_NUMBER;    ADDRESS          HASH_VALUE SQL_ID        CHILD_NUMBER PREDICATE                                  RANGE_ID LOW        HIGH  ---------------- ---------- ------------- ------------ ---------------------------------------- ---------- ---------- ----------  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            1 =X                                                0 0.711697   0.869852  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            2 =X                                                0 0.035482   0.043367      LHR@orclasm > SELECT * FROM V$SQL_CS_STATISTICS D WHERE D.SQL_ID='bt8tk3f1tnwcf' ORDER BY D.CHILD_NUMBER;    ADDRESS          HASH_VALUE SQL_ID        CHILD_NUMBER BIND_SET_HASH_VALUE P EXECUTIONS ROWS_PROCESSED BUFFER_GETS   CPU_TIME  ---------------- ---------- ------------- ------------ ------------------- - ---------- -------------- ----------- ----------  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            0           821942781 Y          1              3          54          0  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            1          3197905255 Y          1          61819         522          0  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            2          3279106319 Y          1           3083          16          0    LHR@orclasm >  

从上述计算结果可以看出,现在CHILD_NUMBER为2的Child Cursor对应的可选择率的范围为[0.035482,0.043367],根本就不在之前VSSQL_CS_SELECTIVITY中记录的CHILD_NUMBER为1的Child Cursor所在的可选择率的范围[0.711697,0.869852]之内,所以Oracle此时还是得用硬解析。

由于上述CHILD_NUMBER为2的Child Cursor也是Bind Aware的,所以其对应的可选择率也被记录在了VSSQL_CS_SELECTIVITY中。

注意,这里不存在Cursor合并的过程,因为Cursor合并是指Oracle会合并存储相同执行计划的原有Child Cursor和新生成的Child Cursor。这里CHILD_NUMBER为1的Child Cursor存储的执行计划走的是对索引的索引快速全扫描,而CHILD_NUMBER为2的Child Cursor存储的执行计划则是走的索引范围扫描,即它们各自存储的执行计划是不相同的,所以此时Oracle不能对它们做Cursor合并。

现在将x的值修改为“SYNONYM”:

LHR@orclasm > EXEC :X :='SYNONYM';    PL/SQL procedure successfully completed.    LHR@orclasm > SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=:X;      COUNT(*)  ----------        3718    LHR@orclasm > SELECT A.SQL_TEXT, A.SQL_ID,A.VERSION_COUNT,A.EXECUTIONS FROM V$SQLAREA A WHERE A.SQL_TEXT LIKE 'SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=%';    SQL_TEXT                                                                                 SQL_ID        VERSION_COUNT EXECUTIONS  ---------------------------------------------------------------------------------------- ------------- ------------- ----------  SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=:X                         bt8tk3f1tnwcf             4          5    LHR@orclasm > SELECT A.SQL_ID,A.CHILD_NUMBER,A.EXECUTIONS,A.BUFFER_GETS,A.IS_BIND_SENSITIVE,A.IS_BIND_AWARE,A.IS_SHAREABLE,A.PLAN_HASH_VALUE FROM V$SQL A WHERE A.SQL_ID='bt8tk3f1tnwcf';    SQL_ID        CHILD_NUMBER EXECUTIONS BUFFER_GETS I I I PLAN_HASH_VALUE  ------------- ------------ ---------- ----------- - - - ---------------  bt8tk3f1tnwcf            0          2         309 Y N N      3002671579  bt8tk3f1tnwcf            1          1         522 Y Y Y      4256744017  bt8tk3f1tnwcf            2          1          16 Y Y N      3002671579  bt8tk3f1tnwcf            3          1          79 Y Y Y      3002671579    LHR@orclasm >  

从查询结果可以看到目标SQL对应的列VERSION_COUNT的值从之前的3变为现在的4,列EXECUTIONS的值为5,说明Oracle在第5次执行目标SQL时依然用的是硬解析。从上述查询结果可以看到,Oracle此时新生成了一个CHILD_NUMBER为3的Child Cursor,并且把存储相同执行计划的CHILD NUMBER为2的原有Child Cursor标记为非共享。

该SQL现在的执行计划为如下所示:

LHR@orclasm > SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('bt8tk3f1tnwcf',3,'advanced'));    PLAN_TABLE_OUTPUT  -----------------------------------------------------------------------------  SQL_ID  bt8tk3f1tnwcf, child number 3  -------------------------------------  SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=:X    Plan hash value: 3002671579    ---------------------------------------------------------------------------------------  | Id  | Operation         | Name              | Rows  | Bytes | Cost (%CPU)| Time     |  ---------------------------------------------------------------------------------------  |   0 | SELECT STATEMENT  |                   |       |       |    18 (100)|          |  |   1 |  SORT AGGREGATE   |                   |     1 |     7 |            |          |  |*  2 |   INDEX RANGE SCAN| IDX_ACS_OBJID_LHR |  3718 | 26026 |    18   (0)| 00:00:01 |  ---------------------------------------------------------------------------------------    Query Block Name / Object Alias (identified by operation id):  -------------------------------------------------------------       1 - SEL$1     2 - SEL$1 / T@SEL$1    Outline Data  -------------      /*+        BEGIN_OUTLINE_DATA        IGNORE_OPTIM_EMBEDDED_HINTS        OPTIMIZER_FEATURES_ENABLE('11.2.0.3')        DB_VERSION('11.2.0.3')        ALL_ROWS        OUTLINE_LEAF(@"SEL$1")        INDEX(@"SEL$1" "T"@"SEL$1" ("T_ACS_20170611_LHR"."OBJECT_TYPE"))        END_OUTLINE_DATA    */    Peeked Binds (identified by position):  --------------------------------------       1 - :X (VARCHAR2(30), CSID=852): 'SYNONYM'    Predicate Information (identified by operation id):  ---------------------------------------------------       2 - access("T"."OBJECT_TYPE"=:X)    Column Projection Information (identified by operation id):  -----------------------------------------------------------       1 - (#keys=0) COUNT(*)[22]  

从上述显示内容可以看出,该SQL现在的执行计划走的还是对索引的索引范围扫描,确实与CHILD_NUMBER为2的原有Child Cursor中存储的执行计划相同。注意到“Peeked Binds”部分的内容为“1 – :X (VARCHAR2(30), CSID=852): 'SYNONYM'”,这说明Oracle在硬解析该SQL的过程中确实再次使用了绑定变量窥探,并且做“窥探”这个动作时看到的绑定变量攴的输入值为“SYNONYM”。

对于上述CHILD_NUMBER为3的Child Cursor,绑定变量X的输入值为“SYNONYM”时对应的记录数为3718,表TI的记录数为78174,将值带入前面合并后的计算公式:

LHR@orclasm > SELECT ROUND(0.9*(3718/78174),6) low,ROUND(1.1*(3718/78174),6) HIGH FROM DUAL;           LOW       HIGH  ---------- ----------    0.042805    0.052317    LHR@orclasm > SELECT * FROM V$SQL_CS_SELECTIVITY D WHERE D.SQL_ID='bt8tk3f1tnwcf' ORDER BY CHILD_NUMBER;    ADDRESS          HASH_VALUE SQL_ID        CHILD_NUMBER PREDICATE                                  RANGE_ID LOW        HIGH  ---------------- ---------- ------------- ------------ ---------------------------------------- ---------- ---------- ----------  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            1 =X                                                0 0.711697   0.869852  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            2 =X                                                0 0.035482   0.043367  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            3 =X                                                0 0.035482   0.052317    LHR@orclasm > SELECT * FROM V$SQL_CS_STATISTICS D WHERE D.SQL_ID='bt8tk3f1tnwcf' ORDER BY D.CHILD_NUMBER;    ADDRESS          HASH_VALUE SQL_ID        CHILD_NUMBER BIND_SET_HASH_VALUE P EXECUTIONS ROWS_PROCESSED BUFFER_GETS   CPU_TIME  ---------------- ---------- ------------- ------------ ------------------- - ---------- -------------- ----------- ----------  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            0           821942781 Y          1              3          54          0  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            1          3197905255 Y          1          61819         522          0  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            2          3279106319 Y          1           3083          16          0  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            3          3683986157 Y          1           3719          79          0  

从上述计算结果可以看出,现在CHILD_NUMBER为3的Child Cursor对应的可选择率范围为[0.042805,0.052317],根本就不在之前V$SQL_CS_SELECTIVITY中记录的CHILD NUMBER为1的Child Cursor对应的可选择率范围[0.711697,0.869852]之内,也不在CHILD_NUMBER为2的Child Cursor对应的可选择率范围[0.035482,0.052317]之内,所以Oracle此时还是得用硬解析。

注意,和之前有所不同的是,现在Oracle就能做cursor合并了。因为现在CHILD_NUMBER为2的原有Child Cursor和CHILD_NUMBER为3的新Child Cursor存储的执行计划都是走对索引的索引范围扫描,即它们各自存储的执行计划是相同的,所以此时Oracle就可以对它们做Cursor合并。

Cursor合并的过程也包括对各自所对应的可选择率范围的合并,合并的原则就是扩展,即要么扩展新Child cursor对应的可选择率范围的下限,要么扩展新Child Cursor对应的可选择率范围的上限。原有Child Cursor对应的可选择率范围是[0.035482,0.052317],新Child Cursor对应的可选择率范围为[0.042805,0.052317],而0.035482是小于0.042805的,所以这里Oracle对新Child Cursor的可选择率范围的下限做了扩展,扩展后该Child Cursor对应的可选择率范围就变成了[0.035482,0.052317],即从V$SQL_CS_SELECTIVITY查询出来的CHILD_NUMBER为3的新Child Cursor的可选择率范围。

现在将的值修改为“JAVA CLASS”,然后再次执行目标SQL:

LHR@orclasm > EXEC :X :='JAVA CLASS';    PL/SQL procedure successfully completed.    LHR@orclasm > SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=:X;      COUNT(*)  ----------        2381    LHR@orclasm > SELECT A.SQL_TEXT, A.SQL_ID,A.VERSION_COUNT,A.EXECUTIONS FROM V$SQLAREA A WHERE A.SQL_TEXT LIKE 'SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=%';    SQL_TEXT                                                                                 SQL_ID        VERSION_COUNT EXECUTIONS  ---------------------------------------------------------------------------------------- ------------- ------------- ----------  SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=:X                         bt8tk3f1tnwcf             5          6    LHR@orclasm > SELECT A.SQL_ID,A.CHILD_NUMBER,A.EXECUTIONS,A.BUFFER_GETS,A.IS_BIND_SENSITIVE,A.IS_BIND_AWARE,A.IS_SHAREABLE,A.PLAN_HASH_VALUE FROM V$SQL A WHERE A.SQL_ID='bt8tk3f1tnwcf';    SQL_ID        CHILD_NUMBER EXECUTIONS BUFFER_GETS I I I PLAN_HASH_VALUE  ------------- ------------ ---------- ----------- - - - ---------------  bt8tk3f1tnwcf            0          2         309 Y N N      3002671579  bt8tk3f1tnwcf            1          1         522 Y Y Y      4256744017  bt8tk3f1tnwcf            2          1          16 Y Y N      3002671579  bt8tk3f1tnwcf            3          1          79 Y Y N      3002671579  bt8tk3f1tnwcf            4          1          74 Y Y Y      3002671579  

从如下查询结果可以看到目标SQL对应的列VERSION_COUNT的值从之前的4变为了现在的5,列EXECUTIONS的值为6,说明Oracle在第6次执行目标SQL时依然用的是硬解析。从查询结果可以看到,Oracle此时新生成了一个CHILD_NUMBER为4的Child Cursor,并且把存储相同执行计划的CHILD NUMBER为3的原有Child Cursor标记为非共享。

目标SQL现在的执行计划为如下所示:

LHR@orclasm > SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('bt8tk3f1tnwcf',4,'advanced'));    PLAN_TABLE_OUTPUT  ----------------------------------------------------------------------------  SQL_ID  bt8tk3f1tnwcf, child number 4  -------------------------------------  SELECT COUNT(*) FROM T_ACS_20170611_LHR T WHERE T.OBJECT_TYPE=:X    Plan hash value: 3002671579    ---------------------------------------------------------------------------------------  | Id  | Operation         | Name              | Rows  | Bytes | Cost (%CPU)| Time     |  ---------------------------------------------------------------------------------------  |   0 | SELECT STATEMENT  |                   |       |       |    12 (100)|          |  |   1 |  SORT AGGREGATE   |                   |     1 |     7 |            |          |  |*  2 |   INDEX RANGE SCAN| IDX_ACS_OBJID_LHR |  2381 | 16667 |    12   (0)| 00:00:01 |  ---------------------------------------------------------------------------------------    Query Block Name / Object Alias (identified by operation id):  -------------------------------------------------------------       1 - SEL$1     2 - SEL$1 / T@SEL$1    Outline Data  -------------      /*+        BEGIN_OUTLINE_DATA        IGNORE_OPTIM_EMBEDDED_HINTS        OPTIMIZER_FEATURES_ENABLE('11.2.0.3')        DB_VERSION('11.2.0.3')        ALL_ROWS        OUTLINE_LEAF(@"SEL$1")        INDEX(@"SEL$1" "T"@"SEL$1" ("T_ACS_20170611_LHR"."OBJECT_TYPE"))        END_OUTLINE_DATA    */    Peeked Binds (identified by position):  --------------------------------------       1 - :X (VARCHAR2(30), CSID=852): 'JAVA CLASS'    Predicate Information (identified by operation id):  ---------------------------------------------------       2 - access("T"."OBJECT_TYPE"=:X)    Column Projection Information (identified by operation id):  -----------------------------------------------------------       1 - (#keys=0) COUNT(*)[22]      49 rows selected.  

从上述显示内容可以看出,目标SQL现在的执行计划走的还是对索引的索引范围扫描,确实与CHILD_NUMBER为3的原有Child Cursor中存储的执行计划相同。注意,“Peeked Binds”部分的内容为“1 – :X (VARCHAR2(30), CSID=852): 'JAVA CLASS'”,说明Oracle在硬解析上述SQL的过程中确实再次使用了绑定变量窺探,并且做“窥探”这个动作时看到的绑定变量的输入值为"JAVA CLASS”。

对于上述CHILD_NUMBER为4的Child Cursor,绑定变量X的输入值为“JAVA CLASS”时对应的记录数为2381,表TI的记录数为78174,带入合并后的计算公式:

LHR@orclasm > SELECT ROUND(0.9*(2381/78174),6) low,ROUND(1.1*(2381/78174),6) HIGH FROM DUAL;           LOW       HIGH  ---------- ----------    0.027412    0.033503    LHR@orclasm > SELECT * FROM V$SQL_CS_SELECTIVITY D WHERE D.SQL_ID='bt8tk3f1tnwcf' ORDER BY CHILD_NUMBER;    ADDRESS          HASH_VALUE SQL_ID        CHILD_NUMBER PREDICATE                                  RANGE_ID LOW        HIGH  ---------------- ---------- ------------- ------------ ---------------------------------------- ---------- ---------- ----------  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            1 =X                                                0 0.711697   0.869852  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            2 =X                                                0 0.035482   0.043367  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            3 =X                                                0 0.035482   0.052317  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            4 =X                                                0 0.027412   0.052317    LHR@orclasm > SELECT * FROM V$SQL_CS_STATISTICS D WHERE D.SQL_ID='bt8tk3f1tnwcf' ORDER BY D.CHILD_NUMBER;    ADDRESS          HASH_VALUE SQL_ID        CHILD_NUMBER BIND_SET_HASH_VALUE P EXECUTIONS ROWS_PROCESSED BUFFER_GETS   CPU_TIME  ---------------- ---------- ------------- ------------ ------------------- - ---------- -------------- ----------- ----------  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            0           821942781 Y          1              3          54          0  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            1          3197905255 Y          1          61819         522          0  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            2          3279106319 Y          1           3083          16          0  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            3          3683986157 Y          1           3719          79          0  00000000AA2108A8 2207936910 bt8tk3f1tnwcf            4          4071504174 Y          1           2382          74          0  

从上述计算结果可以看出,现在CHILD_NUMBER为4的Child Cursor对应的可选择率范围为[0.027412,0.033503],根本就不在之前V$SQL_CS_SELECTIVITY中记录的之内,所以Oracle此时还是得用硬解析。和之前一样,Oracle现在也得做Cursor合并。只不过这次是扩展新Child Cursor对应的可选择率范围的上限。CHILD_NUMBER为3的原有Child Cursor对应的可选择率范围为[0.035482,0.052317],CHILD_NUMBER为4的新Child Cursor对应的可选择率范围为[0.027412,0.033503],而0.052317是大于0.033503的,所以这里Oracle对新Child Cursor的可选择率范围的上限做了扩展,扩展后该Child Cursor对应的可选择率范围就变成[0.027412,0.052317]。