我们上面提到了,在v$sql_cs_histogram视图中,如果此游标的3个桶中出现了两个桶中的count都有非0值,那么此后的解析都要窥探绑定变量的值计算谓词选择率,如果计算选择率不在现有的游标的选择率范围内,就会基于窥探到的绑定变量的值重新硬解析产生一个新的游标,当然这个新游标的执行计划可能与之前是一样的。我们还是来看一个例子就会非常明白这种机制了。
SQL>create table t as select 1 id,a.* from dba_objects a,dba_objects b where rownum<10;
Table created.
SQL>create index t_ind on t(id);
Index created.
SQL>insert into t select 2,a.* from dba_objects a,dba_objects b where rownum<1000;
999 rows created.
SQL>insert into t select 3 ,a.* from dba_objects a,dba_objects b where rownum<10000;
9999 rows created.
SQL>insert into t select 4 ,a.* from dba_objects a,dba_objects b where rownum<100000;
99999 rows created.
SQL>insert into t select 5 ,a.* from dba_objects a,dba_objects b where rownum<1000000;
999999 rows created.
SQL>commit;
Commit complete.
SQL>begin
2 dbms_stats.gather_table_stats(user,
3 't',
4 method_opt => 'for columns status size 5',
5 cascade => true);
6
7 end;
8 /
SQL>select id,count(*) from t group by id order by id;
ID COUNT(*)
---------- ----------
1 9
2 999
3 9999
4 99999
5 999999
上面的代码精心构造了一个例子,表t上的id字段一共有5个唯一值,每个值的数量都不一样,id字段上有索引,分析了直方图。在这种情况下,如果我们直接使用字符变量不使用绑定变量的话,id在对1,2,3,4做查询的时候,都会使用索引扫描,这种情况下,索引扫描的成本要比全表扫描的成本低,id在对5做查询时,会使用全表扫描,这种情况下全表扫描的成本要比索引扫描成本低。如下表格,我是通过explain工具,使用文本变量后,得出的每个执行计划的cost,可以看到全表扫描的cost为2911,在查询id<5的情况下,由于索引扫描的cost都小于全表扫描的cost因此执行计划都选择了走索引扫描,只有在查询id等于5的时,才选择了走全表扫描。
ID
执行计划
COST
选择率
1
索引扫描
4
0.0000081
2
索引扫描
16
0.000899186
3
索引扫描
139
0.008999959
4
索引扫描
1370
0.090007696
5
索引扫描
13690
0. 900085058
5
全表扫描
2911
0. 900085058
上面的表格最后一列提供了谓词的选择率,此处选择率的计算公式为:
选择率=id=?的值在表中的数量/总数量
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。