Oracle中B-tree索引的访问方法(四)-- 索引范围扫描
  IE5LYMWlmdvL 2023年11月14日 31 0

索引的访问方法之范围扫描

索引范围扫描(INDEX RANGE SCAN)可以发生在唯一索引之上,也可以发生在非唯一索引之上。索引范围扫描也是我们最常见到的索引访问方法。索引范围扫描时,并不会像索引唯一扫描那样,一找到满足相关条件的索引条目后即停止,不会再有尝试扫描后续索引条目的动作。而是会一直扫描到第一条不满足相关条件的索引条目后才会停止。这可能是称之为范围扫描的重要原因。而且,当访问的索引不是唯一索引时,即便是在索引列上进行相等的逻辑比较操作,也会访问多个索引条目,并且可能找到多个满足过滤条件的索引条目。

下面,我们沿用索引唯一扫描中构建的表,删除c1列上原有的唯一索引,在c1列上新建一个非唯一索引。然后观察索引范围扫描的访问方法。

Oracle中B-tree索引的访问方法(四)-- 索引范围扫描_范围扫描


图 41

我们构造一个索引范围扫描的行为。如下图所示:

Oracle中B-tree索引的访问方法(四)-- 索引范围扫描_范围扫描_02


图 42

如上图所示,样例SQL中产生了索引范围扫描(INDEX RANGE SCAN)。而且,如果还有印象,这个查询与在索引唯一扫描中进行的测试SQL是完全相同的,只不过此时使用的索引已经不是唯一索引了。

我们还是用10200 event来跟踪对索引块访问的次序,为节省篇幅,详细的操作步骤这里不再重复,操作方法与索引唯一扫描中的相应操作是类似的。这里,只展示跟踪的结果:

Oracle中B-tree索引的访问方法(四)-- 索引范围扫描_b-tree_03


图 43

如上图所示,我们发现发生了4次数据块的一致性读访问。其中最后两次访问的是同一个数据块。我们结合相应索引的树形结构信息来看一下(被访问的数据块已用红框标识):

Oracle中B-tree索引的访问方法(四)-- 索引范围扫描_b-tree_04


图 44

我们可以看到,最先访问的是“0x01801e43”这个地址的数据块,它是索引IND_TAB_C1的根块,其次访问的是“0x01801e56”,它是索引的分支块,再然后访问的是“0x01801e4b”,它是索引的叶子块,最后,对这个叶子块又重复访问了一次。

但是,我们不要因此而得出,索引范围扫描会对访问的叶子块扫描两次的结论。之所以产生这种现象,是因为在SQLPLUS中每次执行SELECT 类SQL,当找到第1行之后,Oracle数据库就要立即处理该行,并进行一些相关处理工作。然后,再按照ARRAYSIZE设置的行数,每凑够这些行数,就再处理一次,然后再继续(更详细的说明,可参考我在墨天轮上发布的相关实验过程的文章进行理解。文章链接为:https://www.modb.pro/db/61256)。我们上面的例子中,虽然最终只返回了一行,但由于我们并不是在唯一索引上进行的相等过滤,所以,理论上,是有可能有重复值。因此,在处理过程中,仍需要再回到索引,做进一步的搜索。也就是说,第一次访问“0x01801e4b”这个叶子块,是因为在该叶子块上找到了第一行匹配的索引条目。而第二次访问,是因为还需要继续搜索,所以,需要继续在该叶子块中搜索是否仍有满足该条件的索引条目。

如果我们在样例查询SQL中,加入“rownum=1”的条件,即只需要返回一行。我们再来跟踪,看看其表现。如下图所示:

Oracle中B-tree索引的访问方法(四)-- 索引范围扫描_b-tree_05


图 45

查看跟踪文件中的内容,如下所示:

Oracle中B-tree索引的访问方法(四)-- 索引范围扫描_范围扫描_06


图 46

如上所示,我们发现最后一个叶子块“0x01801e4b”,只需要访问一次了。这也说明,当SQL中明确注明只返回1行就可以终止时,也就可以在找到1行后,无需再继续搜索其它有可能满足相关过滤条件的,其它记录的操作了。也正因为如此,该叶子块只被访问了一次。

索引范围扫描时,由于不能保证满足条件的索引条目只有一行,所以,在扫描叶子块上的索引条目时,需要一直扫描到出现了比目标值更大的索引条目时才可以终止。

那如果我们要找的目标值,恰好是某叶子块(非最后一个叶子块)上值最大的一个索引条目了,是否还需要扫描后一个叶子块呢?我们仍然通过实验来观察。

首先,我们先DUMP出某个中间叶子块中的内容,以便找到该叶子块中最大的索引条目值。这里,我们选取“leaf: 0x1801e51 25173585 (11: nrow: 13 rrow: 13)”这个叶子块来观察。

Oracle中B-tree索引的访问方法(四)-- 索引范围扫描_b-tree_07


图 47

如上图所示,该叶子块中的最大的索引条目中的值是字符’169’结束的字符串。下面,我们用这个字符串来做过滤条件,执行相应的查询。

Oracle中B-tree索引的访问方法(四)-- 索引范围扫描_范围扫描_08


图 48

查看10200 event 跟踪文件中的内容,如下图所示:

Oracle中B-tree索引的访问方法(四)-- 索引范围扫描_oracle_09


图 49

如上所示,当输入的值,恰好是当前叶子块中的最大值时(即,最后一个索引条目),是会扫描后一个叶子块的。

将前述观察到的访问次序,画成示意图,如下图所示:

Oracle中B-tree索引的访问方法(四)-- 索引范围扫描_索引_10


图50

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月14日 0

暂无评论

推荐阅读
  xaeiTka4h8LY   2024年05月31日   37   0   0 MySQL索引