2014-10-10 155 views
2

我已经阅读了一些有关索引的文档,我做了一些例子,现在我有一些疑惑。为什么选择索引范围扫描通过快速全索引扫描

我创建表和插入的随机值,(A列具有唯一值)列A NOT NULL 创建上A,B,C。(B-TREE)的索引

SELECT COUNT(*) FROM DEMO_FULL_INDEX_SCAN; 
=1000 
SELECT * FROM DEMO_FULL_INDEX_SCAN; 

     A   B   C   D   E   F 
---------- ---------- ---------- ---------- ---------- ---------- 
     1   7  109   1   1   1 
     2   12   83   2   2   2 
     3   21  120   3   3   3 
     4   13   74   4   4   4 
     5   2   1   5   5   5 
... 

文档说,当所有查询值都在索引中时,这些值是从索引(INDEX FAST FULL SCAN)收集的,但这里优化器正在选择另一个操作。

EXPLAIN PLAN FOR 
SELECT A,B,C FROM DEMO_FULL_INDEX_SCAN WHERE A = 1; 
-------------------------------------------------------------------- 
| Id | Operation   | Name  | Rows | Bytes | Cost | 
-------------------------------------------------------------------- 
| 0 | SELECT STATEMENT  |    |  |  |  | 
|* 1 | INDEX RANGE SCAN | FIS_01  |  |  |  | 
-------------------------------------------------------------------- 

我必须指定一个提示优化器选择索引快速全扫描(但我不知道我为什么要指定它)

EXPLAIN PLAN FOR 
SELECT /*+ INDEX_FFS(DEMO_FULL_INDEX_SCAN FIS_01) */A,B,C FROM DEMO_FULL_INDEX_SCAN WHERE A = 1; 
-------------------------------------------------------------------- 
| Id | Operation   | Name  | Rows | Bytes | Cost | 
-------------------------------------------------------------------- 
| 0 | SELECT STATEMENT  |    |  1 | 11 |  2 | 
|* 1 | INDEX FAST FULL SCAN| FIS_01  |  1 | 11 |  2 | 
-------------------------------------------------------------------- 

用另一只手,这方面的例子显示了Oracle文档说。 当在不在索引查询的值,该值由表访问按索引访问ROWID

EXPLAIN PLAN FOR 
SELECT D FROM DEMO_FULL_INDEX_SCAN WHERE A = 800; 

-------------------------------------------------------------------------------- 
-------------------------------------------------------------------------------- 
| Id | Operation     | Name     | Rows | Bytes | Co 
-------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT   |      |  |  | 
| 1 | TABLE ACCESS BY INDEX ROWID| DEMO_FULL_INDEX_SCAN |  |  | 
|* 2 | INDEX RANGE SCAN   | FIS_01    |  |  | 
-------------------------------------------------------------------------------- 

我的问题是,在为什么甲骨文选择通过快速全索引范围扫描的第一个例子INDEX SCAN。我假设在这里,你不会对一个唯一索引,尽管的独特

select a,b,c from demo_full_index_scan where a = 1; 

回答

5

你,因为你的SQL语句的WHERE子句中的执行索引范围扫描列,即你的表DDL是这样的:

create table demo_full_index_scan ( 
    a number 
, b number 
, c number 
, d number 
    ); 

create index i_demo_full_index_scan on demo_full_index_scan (a, b, c); 

因为你不具有唯一索引Oracle不能肯定地说,在A中的值总是唯一知道的;但是,Oracle确实知道A是索引中的第一列,并且可以在索引中可用值的范围内找到此值。

如果您的WHERE子句尝试基于C列进行筛选,那么您将执行INDEX FULL SCAN,因为C存在于索引中,因此您不需要访问该表,但它不是第一列在指数中:

explain plan for select a,b,c from demo_full_index_scan where c = 1; 
------------------------------------------------------------------------------------------- 
| Id | Operation  | Name     | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |      |  1 | 39 |  1 (0)| 00:00:01 | 
|* 1 | INDEX FULL SCAN | I_DEMO_FULL_INDEX_SCAN |  1 | 39 |  1 (0)| 00:00:01 | 
------------------------------------------------------------------------------------------- 
相关问题