INDEX SKIP SCAN 步骤告诉Oralce要跳跃式扫描这个索引,查询GENDER值有改变的地方,并从那里开始向下读树,然后在所考虑的各个虚拟索引中查询OBJECT_id=42。如果大幅增加GENDER的可取值,如下:
zx@ORCL>alter table t1 modify GENDER varchar2(2);
Table altered.
zx@ORCL>update t1 set gender=(chr(mod(rownum,1024)));
84656 rows updated.
zx@ORCL>commit;
Commit complete.
zx@ORCL>exec dbms_stats.gather_table_stats(user,'T1',cascade=>true);
PL/SQL procedure successfully completed.
zx@ORCL>set autotrace traceonly explain
zx@ORCL>select * from t1 where object_id=42;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 101 | 344 (1)| 00:00:05 |
|* 1 | TABLE ACCESS FULL| T1 | 1 | 101 | 344 (1)| 00:00:05 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=42)
情况2:
在使用select count(*) from t查询(或类似的查询),而且在表T上有一个B*树索引。不过,优化器并不是统计索引条目,而是在全面扫描这个表(尽管索引比表要小)。在这种情况下,索引可能建立在一个允许有NULL值的列上。由于对于索引键完全为null的行不会建立相应的索引条目,所以索引中的行数可能并不是表中的行数。这里优化器的选择是对的,如若不然,倘若它使用索引来统计行数,则可能会得到一个错误的答案。
zx@ORCL>desc t;
Name Null? Type
----------------------------------------------------------------------------------------------------- -------- --------------------------------------------------------------------
X NUMBER
Y NUMBER
Z CHAR(23)
zx@ORCL>select count(*) from t;
Execution Plan
----------------------------------------------------------
Plan hash value: 2966233522
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 153 (1)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T | 99999 | 153 (1)| 00:00:02 |
-------------------------------------------------------------------
zx@ORCL>alter table t modify y not null;
Table altered.
zx@ORCL>desc t
Name Null? Type
----------------------------------------------------------------------------------------------------- -------- --------------------------------------------------------------------
X NUMBER
Y NOT NULL NUMBER
Z CHAR(23)
zx@ORCL>select count(*) from t;
Execution Plan
----------------------------------------------------------
Plan hash value: 2371838348
-----------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 80 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FAST FULL SCAN| IDX_T | 99999 | 80 (0)| 00:00:01 |
-----------------------------------------------------------------------