上一节中,根据公式算出基数的时候,对目标列指定的where查询条件都是在该列的最大值和最小值(统计信息里面的值)之间的。本节讨论,如果对该列的查询条件不在它们之间,即谓词越界的现象。
下面例子:
![](https://i-blog.csdnimg.cn/blog_migrate/61f47297e1353694499cdea2608c546d.png)
点击(此处)折叠或打开
- select T.low_value,T.high_value,DUMP(T.high_value,16),dump(T.low_value,(16)),T.num_distinct,T.num_nulls from dba_tab_col_statistics T where table_name = 'T7' AND column_name = 'OBJECT_ID';
![](https://i-blog.csdnimg.cn/blog_migrate/d0304be348242b67d021ff11070fb264.png)
此时该列的最大值和最小值分别是(因为是raw类型的,需要用下面方法转换成10进制的方法)
SQL> var temp number
SQL> exec dbms_stats.convert_raw_value('C103',:temp);
PL/SQL procedure successfully completed.
TEMP
----------
2
SQL> exec dbms_stats.convert_raw_value('C3085F2F',:temp);
PL/SQL procedure successfully completed.
TEMP
----------
79446
可以看出此时,object_id的最大值和最小值为79446和2。
为了模拟本次实验,我用下面的存储过程插入几万条数据,并且不统计统计信息。
点击(此处)折叠或打开
- declare
- i int;
- begin
- for i in 80000 .. 90000 loop
- insert into t7
- (OWNER,
- OBJECT_NAME,
- SUBOBJECT_NAME,
- OBJECT_ID,
- DATA_OBJECT_ID,
- OBJECT_TYPE,
- CREATED,
- LAST_DDL_TIME,
- TIMESTAMP,
- STATUS,
- TEMPORARY,
- GENERATED,
- SECONDARY,
- NAMESPACE,
- EDITION_NAME)
- values
- ('SYS',
- 'ICOL$',
- null,
- i,
- 2,
- 'TABLE',
- to_date('12-12-2014 02:51:05', 'dd-mm-yyyy hh24:mi:ss'),
- to_date('12-12-2014 02:51:05', 'dd-mm-yyyy hh24:mi:ss'),
- '2014-12-12:02:51:05',
- 'VALID',
- 'N',
- 'N',
- 'N',
- 1,
- null);
- end loop;
-
- end;
但此时表中列的最大值是 120000
![](https://i-blog.csdnimg.cn/blog_migrate/b59de26702760fffe3e68537787a5f3b.png)
此时我们再执行以下语句
![](https://i-blog.csdnimg.cn/blog_migrate/a4c840a6487ea1a03f1c9823b2c63472.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1a15c1da2fed6e9cdb10bb841c6ed95e.png)
因为没有收集统计信息,所以统计信息都没有变化。
上面的结果集是40000多条数据,cbo计算出的cardinality确为1,这里就是出现了“谓词越界”的现象,即如果对目标列指定的
where查询条件不在该列的最大值和最小值之间,cbo就无法判断出针对该列的查询条件的可选择率,所以只能用一个估算值来
作为针对该目标列的查询条件的可选择率。进而是cbo选错执行计划。
可以针对上述,做一个10053的trace。
![](https://i-blog.csdnimg.cn/blog_migrate/d5aece46b52cba2da2cd6f4bb432911d.png)
这里出现了谓词越界的现象,cbo用了一个很小的值0.000015来做为返回的基数。出现了严重的偏差。进而导致cbo选错了执行计划。
再次收集统计信息后,统计信息回归正常,如下:
![](https://i-blog.csdnimg.cn/blog_migrate/c37ac23a8cdb5e4b3a8bab7e7e4368e5.png)
此时再执行如上语句,变为了
![](https://i-blog.csdnimg.cn/blog_migrate/1a280aa2b18242ed4c7d2ecbc39e2f6a.png)
效率更高。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30109892/viewspace-1828404/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30109892/viewspace-1828404/