加了索引还是不起效的情况,有可能是一种基数反馈机制导致的,解决方法关闭基数反馈机制。
如:添加hint /*+ opt_param('_optimizer_use_feedback','false')*/
关闭动态采样 :
SQL> alter session set optimizer_dynamic_sampling=0; Session altered.

获取 sharepool 中使用基数反馈的子游标。
SQL> select sql_ID,USE_FEEDBACK_STATS FROM V$SQL_SHARED_CURSOR where USE_FEEDBACK_STATS ='Y'; SQL_ID U ------------- - 0mp85ftwxaky5 Y
从图中可以看出,当前已经关闭动态采样,第一次执行 SQL 时, E-Rows 1014 与 A-Rows 1 相差过大,当第二次执行时,可以看出相差很小,说明发生了基数反馈 cardinality feedback ,也就是 CBO 考虑了上次执行获取的 cardinality ( cardinality feedback used for this statement )。
在下列情况 CBO 可能无法估算出准确的 Cardinality , Oracle 会启用 CFB 功能:
1. 没有收集表的统计信息,并且 dynamic sampling 也没有开启;
2. 一个表的查询条件涉及多列,但却没有收集扩展的统计信息 (extended statistics)
3. 查询条件复杂(比如条件有函数)
针对上述情况, Oracle 会采取如下的 CFB 流程处理:
1.SQL 语句第一次执行时, Oracle 会监控操作的实际行数( A-Row ),然后对比 CBO 估算的行数( E-Row )。
2. 如果两个值相差很大,就记录实际行数( A-Row ),做上标记。下次执行时再次进行硬解析,根据实际行数来重新生成执行计划。
3. 如果两个值相差不大, CBO 就不再监控这条 SQL 语句。
