Oracle全索引扫描

全索引扫描
全索引扫描是读取给定索引中所有条目的操作。从这个意义上说,全索引扫描类似于全表扫描。与首先做全表扫描,然后再对数据排序相比,全索引扫描是一种很好的替代方法。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,又因为这种类型的扫描可以像全表扫描那样并行运行,所以这种类型的扫描往往更快。

发表评论

电子邮件地址不会被公开。