Oracle执行计划中的Access和Filter谓词

时间:2009-09-23 07:31:17

标签: oracle optimization oracle-sqldeveloper

Oracle执行计划中的Access和Filter谓词有什么区别? 如果我理解正确,“访问”用于确定需要读取哪些数据块,并在读取块后应用“过滤器”。因此,过滤是“邪恶的”。

在下面的执行计划的谓词信息部分的示例中:

10 - access("DOMAIN_CODE"='BLCOLLSTS' AND "CURRENT_VERSION_IND"='Y')
     filter("CURRENT_VERSION_IND"='Y')

为什么在“访问”和“过滤”部分中都会重复“CURRENT_VERSION_IND”?

相应的操作是索引上的INDEX RANGE扫描,它在字段(DOMAIN_CODE,CODE_VALUE,CURRENT_VERSION_IND,DECODE_DISPLAY)上定义。

我的猜测是因为CURRENT_VERSION_IND不是索引中的第二列,所以Oracle在Access阶段不能使用它。因此,它通过DOMAIN_CODE列访问索引,获取所有块,然后按CURRENT_VERSION_IND过滤它们。我是对的吗?

2 个答案:

答案 0 :(得分:6)

不,此示例中的访问谓词表示DOMAIN_CODECURRENT_VERSION_IND正在遍历索引。

我不担心看起来多余的过滤谓词 - 这似乎是解释计划的一个怪癖,可能与它必须对索引进行一种跳过扫描这一事实有关(它会对第一列进行范围扫描,然后对CODE_VALUE进行跳过扫描,搜索任何匹配的CURRENT_VERSION_IND s。

是否需要修改索引或创建另一个索引完全是另一回事。

另外,只是为了纠正一个小小的误解:无论是执行“访问”还是“过滤”步骤,都必须从索引中获取块,然后才能执行任何操作。如果您指的是从表中获取块,那么答案也是否定的 - 您说过滤器谓词“10”在索引访问上,而不在表访问上;无论如何,Oracle没有理由不评估索引上的CURRENT_VERSION_IND上的过滤器 - 它根本不需要访问该表,除非它需要索引中未包含的其他列。

答案 1 :(得分:2)

我相信你对甲骨文正在做什么的评估是正确的,但错误地说过滤步骤(或任何其他优化器选择)始终是“邪恶的”。绝对索引可能被查询的每个可能的列组合是没有意义的,因此经常需要过滤。

但是,如果在这种情况下,将CURRENT_VERSION_IND添加为索引的第二列可以显着提高频繁运行查询的性能不会损害其他查询的性能,那么可能有意义如此。