Oracle执行计划中的“访问谓词”和“过滤谓词”有什么区别? 如果我理解正确的话,“访问”用于确定需要读取哪些数据块,“过滤”在读取块后应用。因此,过滤是“邪恶的”。
在下面执行计划的谓词信息部分的示例中:
10 - access("DOMAIN_CODE"='BLCOLLSTS' AND "CURRENT_VERSION_IND"='Y')
filter("CURRENT_VERSION_IND"='Y')
为什么“CURRENT_VERSION_IND”在“Access”和“Filter”部分中重复出现?
对应的操作是
INDEX RANGE
扫描索引,索引是在字段(DOMAIN_CODE
,CODE_VALUE
,CURRENT_VERSION_IND
,DECODE_DISPLAY
)上定义的。
我的猜测是,因为
CURRENT_VERSION_IND
不是索引中的第二列,Oracle在“Access”阶段无法使用它。因此,它通过 DOMAIN_CODE
列访问索引,获取所有块,然后通过 CURRENT_VERSION_IND
过滤它们。我说得对吗?
不,此示例中的访问谓词表示索引正在被
DOMAIN_CODE
和 CURRENT_VERSION_IND
遍历。
我不会担心过滤谓词看起来是多余的 - 这似乎是解释计划的一个怪癖,可能与它必须对索引进行某种跳跃扫描这一事实有关(它确实对第一列进行范围扫描,然后对
CODE_VALUE
进行跳跃扫描,搜索任何匹配的 CURRENT_VERSION_IND
)。
是否需要修改索引或创建另一个索引完全是另一回事。
另外,只是为了纠正一个小误解:必须先从索引中获取块,然后才能执行任何操作,无论是执行“访问”还是“过滤”步骤。如果您指的是从表中获取块,那么答案是否定的 - 您说过滤谓词“10”是在索引访问上,而不是在表访问上;无论如何,Oracle 没有理由无法评估索引上
CURRENT_VERSION_IND
上的过滤器 - 它根本不需要访问表,除非它需要索引中未包含的其他列。
我相信您对 Oracle 正在做的事情的评估是正确的,但说过滤器步骤(或任何其他优化器选择)始终是“邪恶的”是错误的。 对可能查询的列的所有可能组合建立索引是没有意义的,因此经常需要过滤。
但是,如果在这种情况下添加 CURRENT_VERSION_IND 作为索引的第二列,可以显着提高频繁运行的查询的性能并且不会损害其他查询的性能,那么这样做可能是有意义的。