我有一个users
表,其中包含username
列,以及此列中的B树索引。当我检查以下查询的解释计划时:select username from users where username like 'A%'
我可以看到Oracle对索引执行索引范围扫描以提取所需信息,这是绝对正常的,但在索引范围内扫描Oracle使用以下内容谓词:access(username like 'A%')
filter(username like 'A%')
。
为什么Oracle会同时使用它们?它们是完全相同的,所以我认为其中一个就足够了。
答案 0 :(得分:0)
这不是答案,只是一些链接和引用:
访问谓词(“访问”) 访问谓词表示叶节点遍历的开始和停止条件。
索引过滤谓词(索引操作的“过滤器”) 索引过滤器谓词仅在叶节点遍历期间应用。它们不会影响启动和停止条件,也不会缩小扫描范围。
表级过滤谓词(表操作的“过滤器”) 在表级别上评估不属于索引的列的谓词。为此,数据库必须首先从表中加载行。
简而言之,正如Tom Kyte所说:
访问意味着我们正在使用某些东西来访问"数据 - 我们只是"访问"相关数据。 过滤意味着我们需要获得更多数据,并在获得数据后对其进行过滤。过滤器将应用于所有行,仅应用于通过过滤器的行
https://asktom.oracle.com/pls/apex/f?p=100:11:::NO:RP:P11_QUESTION_ID:7807480400346035212
在Oracle Youtube频道上也有很好的视频:https://www.youtube.com/watch?v=K0f2Yzue7yw
答案 1 :(得分:0)
Oracle(IMO)的理念与您的期望相反。 FILTER谓词不仅在明显的情况中减少,而且有时会在额外的过滤条件下进行扩展。
小例子
select * from tst where c1 like 'A%' and c1 like '%A'
产量
2 - access("C1" LIKE 'A%')
filter("C1" IS NOT NULL AND "C1" LIKE 'A%' AND "C1" LIKE '%A')
因此添加了额外的NOT NULL约束。
我只能推测,过滤处理比访问(在内存中)更便宜,因此双重检查比几个CPU周期更好。很有可能的是,Oracle必须处理特殊情况,其中访问可能提供的内容多于谓词中定义的内容,例如对集群表的访问。