11

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 过滤它们。我对吗?

4

2 回答 2

8

不,此示例中的访问谓词表明索引正在被DOMAIN_CODE和遍历CURRENT_VERSION_IND

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

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

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

于 2009-09-24T14:37:26.207 回答
3

我相信您对 Oracle 正在做的事情的评估是正确的,但是说过滤步骤(或任何其他优化器选择)总是“邪恶的”是错误的。绝对索引可能查询的列的所有可能组合是没有意义的,因此经常需要过滤。

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

于 2009-09-23T11:47:18.867 回答