全索引扫描
全索引扫描是读取给定索引中所有条目的操作。从这个意义上说,全索引扫描类似于全表扫描。与首先做全表扫描,然后再对数据排序相比,全索引扫描是一种很好的替代方法。Oracle数据库在下面任何一种情况下都可能使用全索引扫描。
.查询需要排序合并连接(sort merge join):查询所引用的所有列必须都在索引中存在,且前导索引列的顺序也必须与查询中指定的列顺序相同。
.查询包含order by子句:子句中的所有列必须都在该索引中存在。
.查询包含group by子句:索引和group by子句必须包含相同的列,但不要求它们的顺序一定相同。
下面的例子显示数据库如何利用全索引扫描操作检索数据,而无需执行排序操作。因为索引已经排序,所以使用全索引扫描可以不必执行排序操作。全索引扫描读取单个个数据块,而不执行多块读取操作。
SQL> select * from test where c<30000 order by c; 29999 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 2983339933 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 29999 | 292K| 26 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| TEST | 29999 | 292K| 26 (0)| 00:00:01 | |* 2 | INDEX FULL SCAN | TEST_I1 | 29999 | | 14 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("C"<30000)
在此查询中,数据库首先执行全索引扫描,然后通过索引rowid操作执行表访问。这是因为查询请求了除索引列外的其他列(select * from …)。然而,如果查询只请求了索引列并使用了order by子句,数据库将跳过表访问,只通过访问索引得到数据,无需读取表中的值。
索引快速全扫描
当索引本身包含查询中指定的所有列时,Oracle数据库执行索引快速全扫描代替全表扫描。请注意,在下面的例子中,检索数据只用了索引快速全扫描操作,且根本没有访问表本身:
SQL> select c from test where c<10000; 9999 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 3298034341 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 9999 | 49995 | 123 (1)| 00:00:01 | |* 1 | INDEX FAST FULL SCAN| TEST_I1 | 9999 | 49995 | 123 (1)| 00:00:01 | -------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("C"<10000)
请注意,不像全索引扫描,索引快速全扫描使用多块读操作来读取索引。因此,既因为多块的I/O,又因为这种类型的扫描可以像全表扫描那样并行运行,所以这种类型的扫描往往更快。