Oracle优化器的基础知识(3)

索引唯一性扫描(INDEX UNIQUE SCAN)是针对唯一性索引(UNIQUE INDEX)的扫描,它仅仅适用于where条件里等值查询的目标SQL。因为扫描的对象是唯一性索引,所以索引唯一性扫描的结果至多只会返回一条记录。

3.2.2 索引范围扫描

索引范围扫描(INDEX RANGE SCAN)适用于所有类型的B*Tree索引,当扫描的对象是唯一性索引时,此时目标SQL的where条件一定是范围查询(谓词条件为BETWEEN、<、>等);当扫描的对象是非唯一性索引时,对目标SQL的where条件没有限制(可以是等值查询,也可以是范围查询)。索引范围扫描的结果可能会返回多条记录,其实这就是索引范围扫描中的“范围”二字的本质含义。

在同等条件下,当目标索引的索引行的数量大于1时,索引扫描范围所耗费的逻辑读至少会比生意人索引唯一性扫描的逻辑读多1。因为扫描结果可能会返回多条记录,又因为目标索引的索引行数量大于1,Oracle为了确定索引范围扫描的扫描终点,就不得不去多次访问相关的叶子块。

3.2.3 索引全扫描

索引全扫描(INDEX FULL SCAN)适用于所有类型的B*Tree索引(包括唯一性索引和非唯一性索引)。所谓的“索引全扫描”,就是指要扫描目标索引所有叶子块的所有索引行。这里需要注意的是,索引全扫描需要扫描目标索引的所有叶子块,但并不意味着需要扫描该索引的所有分支块。在默认情况下,Oracle在做索引全扫描时只需通过访问必要的分支块定位到位置该索引最左边的叶子块的第一行索引行,就可以利用该索引叶子块之间的双向指针链表,从左至右依次顺序扫描该索引所有叶子块的所有索引行了。由于索引是有序的,所以索引全扫描的执行结果也是有序的,并且是按照索引的索引键值列来排序,这也意味着走索引全扫描能够既达到排序的效果,又同时避免了对该索引的索引键值列的真正排序操作。

默认情况下,索引全扫描的扫描结果的有序性就决定了索引全扫描是不能够并行执行的,并且通常情况下索引全扫描使用的是单块读。

通常情况下,索引全扫描是不需要回表的,所以索引全扫描适用于目标SQL的查询全部是目标索引的索引键值列的情形。我们知道,对于Oracle数据库的B*Tree索引而言,当所有索引键值列全为NULL值时不入索引,这意味着Oracle中能做索引全扫描的前提条件是目标索引至少有一个索引键值列的属性是NOT NULL。这很显然,如果目标索引的所有索引键值列的属性均为允许NULL值,此时如果还走索引全扫描,就会漏掉目标表中那些索引值列均为NULL的记录,即此时走索引全扫描的结果就不准了!Oracle不允许这种事情发生。

3.2.4 索引快速全扫描

索引快速全扫描(INDEX FAST FULL SCAN)和索引全扫描极为类似,它也适用于所有类型的B*Tree索引。和索引全扫描一样,索引快速全扫描也需要扫描目标索引所有叶子块的所有索引行。

索引快速全扫描与索引全扫描相比有如下三点区别:

1)索引快速全扫描只适用于CBO。

2)索引快速全扫描可以使用多块读,也可以并行执行。

3)索引快速全扫描的执行结果不一定是有序的。这是因为索引快速全扫描时Orace是根据索引行在磁盘上的物理存储顺序来扫描,而不是根据索引行的逻辑顺序来扫描的,所以扫描结果才不一定有序(对于单个索引叶子块的索引行而言,其物理存储顺序和逻辑存储顺序一致;但对于物理存储位置相邻的索引叶子块而言,块与块之间索引行的物理存储顺序则不一定在逻辑上有序)。

3.2.5 索引跳跃式扫描

索引跳跃式扫描(INDEX SKIP SCAN)适用于所有类型的复合B*Tree索引,它使那些在where条件中没有对目标索引的前导列指定查询条件,但同时又对该索引的非前导列指定了查询条件的目标SQL依然可以使用上该索引,这就像是在扫描该索引时跳过了它的前导列,直接从该索引的非前导到开始扫描一样(实际执行过程并非如此),这民是索引跳跃式扫描中“跳跃”(SKIP)一词的含义。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/6d15ed824a6ca3b05750713dcc25cf92.html