首页 > 数据库 > Oracle > 关于索引的几个问题---续集2
4.为什么明明表中建立了索引,但是在执行计划中却显示未使用我的索引,这是为什么呢?
------不适用建立的索引:情况一
drop table t;
create table t as select decode(mod(rownum,2),0,'M','F')gender, all_objects.* from all_objects;
create index t_idx on t(gender,object_id);
begin
dbms_stats.gather_table_stats(user,'T');
end;
---------------------------------------------------------------------------------------------------当索引最前列不是只有几个少数值时,可能会选择全表扫描
---------------------------------------------------------------------------------------------------跳跃式索引,查找gender值开始改变的得房,然后开始向下扫描
select * from t where object_id=42;----SELECT STATEMENT , GOAL = ALL_ROWS 4 1 99
-----TABLE ACCESS BY INDEX ROWID SCOTT T 4 1 99
----INDEX SKIP SCAN SCOTT T_IDX 3 1
update t set gender =chr(mod(rownum,256));
begin
dbms_stats.gather_table_stats(user,'T',cascade => TRUE);
end;
select * from t where object_id=42;
SQL> select * from t t1 where object_id=42;
执行计划
----------------------------------------------------------
Plan hash value: 2053318169
--------------------------------------------------------------------------------
-----
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 99 | 4 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 99 | 4 (0)| 00:00:01 |
|* 2 | INDEX SKIP SCAN | T_IDX | 1 | | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------
-----
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=42)
filter("OBJECT_ID"=42)
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
8 consistent gets
0 physical reads
0 redo size
1681 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
----------------------------------------------------------------------------当索引最前列不是只有几个少数值时,可能会选择全表扫描
SQL> set pagesize 500
SQL> set linesize 500
SQL> explain plan for select * from t where object_id=42;
已解释。
SQL> select * from table(dbms_xplan.display);
Plan hash value: 2053318169
--------------------------------------------------------------------------------
-----
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 99 | 258 (0)| 00:00:04 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 99 | 258 (0)| 00:00:04 |
|* 2 | INDEX SKIP SCAN | T_IDX | 1 | | 257 (0)| 00:00:04 |
--------------------------------------------------------------------------------
-----
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=42)
filter("OBJECT_ID"=42)
已选择15行。
执行计划
----------------------------------------------------------
Plan hash value: 2137789089
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8168 | 16336 | 29 (0)| 00:00:01 |
| 1 | COLLECTION ITERATOR PICKLER FETCH| DISPLAY | 8168 | 16336 | 29 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
统计信息
----------------------------------------------------------
26 recursive calls
12 db block gets
180 consistent gets
0 physical reads
0 redo size
1449 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
15 rows processed
---------------------------------------------------------------------------查找索引列值时会选择索引快速扫描
SQL> select gender,object_id from t where object_id=42;
G OBJECT_ID
- ----------
_ 42
执行计划
----------------------------------------------------------
Plan hash value: 3163761342
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 118 (1)| 00:00:02 |
|* 1 | INDEX FAST FULL SCAN| T_IDX | 1 | 7 | 118 (1)| 00:00:02 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=42)
统计信息
----------------------------------------------------------
1 recursive calls
2 db block gets
461 consistent gets
0 physical reads
0 redo size
598 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
select * from t where y=2;即是当索引列含有两个或两个以上字段时,但是查询的时候谓词使用的只是索引列中一个或不足个字段值时,此时查询为了避免调用索引带来的扫描所有索引列的更大开销,
选择对表做一个全表扫描,而不是索引扫描,但是当使用的谓词只有很少几个不同的值的时候,会选择跳跃式索引。
另一种:select x,y from t where y=2;此时对索引本身进行一个快速的全面扫描,以为这个缩影比底层的表要小得多。
------不适用建立的索引:情况二
-----------------------不适用建立的索引:情况三
索引列上如果要在后面操作中进行函数操作,那么此时我们的操作过程是不会走索引的;
SQL> select * from t1 where x=1;
执行计划
----------------------------------------------------------
Plan hash value: 1369807930
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 130 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| IDX_T1 | 5 | 130 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("X"=1)
Note
-----
- dynamic sampling used for this statement (level=2)
SQL> select * from t1 where to_number(x)>1;
执行计划
----------------------------------------------------------
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T1 | 1 | 26 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER(TO_CHAR("X"))>1)
Note
-----
- dynamic sampling used for this statement (level=2)
SQL>
-----------------------不适用建立的索引:情况四
create table t2(x,y,primary key(x))as select rownum x,object_name from all_objects where rownum<20000;
SQL> select * from t2;
执行计划
----------------------------------------------------------
Plan hash value: 1513984157
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 18845 | 552K| 27 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T2 | 18845 | 552K| 27 (0)| 00:00:01 |
--------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
SQL> select * from t2 where x<50;
执行计划
----------------------------------------------------------
Plan hash value: 3744695385
--------------------------------------------------------------------------------
------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 49 | 1470 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 49 | 1470 | 3 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | SYS_C0011742 | 49 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("X"<50)
Note
-----
- dynamic sampling used for this statement (level=2)
SQL> select * from t2 where x=50;
执行计划
----------------------------------------------------------
Plan hash value: 1738664179
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 30 | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | SYS_C0011742 | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("X"=50)
SQL> select * from t2 where x<15000;
执行计划
----------------------------------------------------------
Plan hash value: 1513984157
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14069 | 412K| 27 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T2 | 14069 | 412K| 27 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("X"<15000)
Note
-----
- dynamic sampling used for this statement (level=2)
SQL>
可以看出,强制使用索引的效率并没有全表扫描效率高!
综上所述:建有索引但是没被使用的情况有很多种,,具体情况需要具体分许!!
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/30018455/viewspace-1386104/ ,如需转载,请注明出处,否则将追究法律责任。