2013-08-07 星期三 天氣:晴
-------------------------------索引的性能分析-----------------------
場景:假設數據塊的大小8000字節,查詢返回的記錄行數是整表記錄的20%
1、表有100000行數據,返回20000行數據,假如每行80字節,1塊=100行,全表有1000塊,
查詢到的對應的葉子行有20000個,掃索引掃20000塊次,全表掃,掃1000塊次。
2、表有100000行數據,返回20000行數據,假如每行800字節,1塊=10行,全表有10000塊,
查詢到的對應的葉子行有20000個,掃索引掃20000塊次,全表掃,掃10000塊次。
3、表有100000行數據,返回20000行數據,假如每行1600字節,1塊=5行,全表有20000塊,
查詢到的對應的葉子行有20000個,掃索引掃20000塊次,全表掃,掃20000塊次。
4、表有100000行數據,返回20000行數據,假如每行8000字節,1塊=1行,全表有100000塊,
查詢到的對應的葉子行有20000個,掃索引掃20000塊次,全表掃,掃100000塊次。
歸納:
A 不一定使用索引查詢效率就會提升,場景1個場景2反而會下降。
B 索引的使用和塊、行的比例有關係,塊中含有的行越多掃索引的效率就會越低,
塊中含有的行越少,掃索引的效率就會越高。和行的密度的有關係。
案例:研究RBO優化法則和CBO性能分析的差別
1、創建一個案例表
SQL> create table tx as select 1 id,object_name from all_objects;
Table created.
SQL> update tx set id=99 where rownum=1;
1 row updated.
SQL> commit;
Commit complete.
2、用RBO優化器生成執行計劃
SQL> set autotrace trace exp
SQL> select /*+ rule */ * from tx where id=1;
Execution Plan
----------------------------------------------------------
Plan hash value: 40191160
----------------------------------
| Id | Operation | Name |
----------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | TABLE ACCESS FULL| TX | --全表掃描
----------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID"=1)
Note
-----
- rule based optimizer used (consider using cbo)
SQL> create index ind_tx on tx(id);
Index created.
SQL> exec dbms_stats.gather_table_stats(user,'tx',cascade=>true);
PL/SQL procedure successfully completed.
SQL> select /*+ rule */ * from tx where id=1;
Execution Plan
----------------------------------------------------------
Plan hash value: 2614573569
----------------------------------------------
| Id | Operation | Name |
----------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| TX |
|* 2 | INDEX RANGE SCAN | IND_TX | --RBO下只要有索引一定會強制走索引的。
----------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=1)
Note
-----
- rule based optimizer used (consider using cbo)
SQL> select /*+ rule */ * from tx where id=99;
Execution Plan
----------------------------------------------------------
Plan hash value: 2614573569
----------------------------------------------
| Id | Operation | Name |
----------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| TX |
|* 2 | INDEX RANGE SCAN | IND_TX |
----------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=99)
Note
-----
- rule based optimizer used (consider using cbo)
================================================
3、用CBO生成執行計劃
SQL> select * from tx where id=1;
Execution Plan
----------------------------------------------------------
Plan hash value: 40191160
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 40919 | 1118K| 47 (3)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TX | 40919 | 1118K| 47 (3)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID"=1)
SQL> select /*+ index(tx ind_tx) */ * from tx where id=1; --CBO下,強制走索引代價很大。
Execution Plan
----------------------------------------------------------
Plan hash value: 2614573569
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 40919 | 1118K| 273 (1)| 00:00:04 |
| 1 | TABLE ACCESS BY INDEX ROWID| TX | 40919 | 1118K| 273 (1)| 00:00:04 |
|* 2 | INDEX RANGE SCAN | IND_TX | 40919 | | 81 (2)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=1)
SQL> set linesize 1000
SQL> select * from tx where id=99;
Execution Plan
----------------------------------------------------------
Plan hash value: 2614573569
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 28 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TX | 1 | 28 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_TX | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=99)
查詢列值分佈數量很高的值,會全表掃,反之,纔可能會用索引。
影響索引使用效率的三個影響因素:
1、塊中行的密度
2、查詢語句中where條件中的索引列引用值在列值中的分佈情況。
3、索引和表數據放在同一個磁盤上,會發生IO的爭用。
---------------------------------------------------
案例:分析B樹索引的性能
SQL> drop table t1;
drop table t1
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> create table t1(id int primary key,name varchar2(10));
Table created.
SQL> begin
2 for i in 1..10000 loop
3 insert into t1 values(i,'T1');
4 end loop;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
SQL> create table t2(id int primary key,name varchar2(10));
Table created.
SQL> begin
2 for i in 1..1000000 loop
3 insert into t2 values(i,'T2');
4 end loop;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_table_stats(user,'t1',cascade=>true);
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_table_stats(user,'t2',cascade=>true);
PL/SQL procedure successfully completed.
SQL> set autotrace trace exp --顯示執行計劃
SQL> select * from t1 where id=100;
Execution Plan
----------------------------------------------------------
Plan hash value: 1846342996
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 6 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 6 | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | SYS_C006531 | 1 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=100)
SQL> select * from t2 where id=100;
Execution Plan
----------------------------------------------------------
Plan hash value: 3288443420
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 7 | 3 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | SYS_C006532 | 1 | | 2 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=100)
T1表的索引數只有兩層,但是T2表的平衡樹有三層,T3表在讀取索引的時候會多讀取一個根塊。
查詢層數:
----------------------------------------------------------
select * from user_indexes; --首先查看對應表的索引名
analyze index 索引名 validate structure; --分析
select * from index_stats --查看索引的統計信息
如下:
SQL> analyze index ind_obj_id validate structure;
Index analyzed
SQL> select * from index_stats;
HEIGHT BLOCKS NAME PARTITION_NAME LF_ROWS LF_BLKS LF_ROWS_LEN LF_BLK_LEN BR_ROWS BR_BLKS BR_ROWS_LEN BR_BLK_LEN DEL_LF_ROWS DEL_LF_ROWS_LEN DISTINCT_KEYS MOST_REPEATED_KEY BTREE_SPACE USED_SPACE PCT_USED ROWS_PER_KEY BLKS_GETS_PER_ACCESS PRE_ROWS PRE_ROWS_LEN OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
---------- ---------- ------------------------------ ------------------------------ ---------- ---------- ----------- ---------- ---------- ---------- ----------- ---------- ----------- --------------- ------------- ----------------- ----------- ---------- ---------- ------------ -------------------- ---------- ------------ -------------- ----------------
2 384 IND_OBJ_ID 115766 273 1843607 7996 272 1 3750 8028 52956 839277 38598 3 2190936 1847357 85 2.9992745738 3.99963728690606 0 0 1 8
兩次查詢的代價是一樣的,有了B樹索引之後,查詢的損耗不會因爲表數據量的增加而增加,
即使數據量相差很大,當在唯一性索引或者主鍵索引查詢的時候,消耗的資源幾乎是沒有區別的,
這就是索引發揮的巨大作用。
如果沒有索引:
SQL> select /*+ full(t1) */ * from t1 where id=100;
Execution Plan
----------------------------------------------------------
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 6 | 6 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T1 | 1 | 6 | 6 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID"=100)
SQL> select /*+ full(t2) */ * from t2 where id=100;
Execution Plan
----------------------------------------------------------
Plan hash value: 1513984157
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 444 (7)| 00:00:06 |
|* 1 | TABLE ACCESS FULL| T2 | 1 | 7 | 444 (7)| 00:00:06 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID"=100)
update操作中索引的影響
SQL> update t1 set id=10001 where id=100;
1 row updated.
Execution Plan
----------------------------------------------------------
Plan hash value: 2799287261
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | 4 | 1 (0)| 00:00:01 |
| 1 | UPDATE | T1 | | | | |
|* 2 | INDEX UNIQUE SCAN| SYS_C006531 | 1 | 4 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=100)
SQL> update /*+ full(t1) */ t1 set id=10001 where id=100;
0 rows updated.
Execution Plan
----------------------------------------------------------
Plan hash value: 2927627013
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | 4 | 6 (0)| 00:00:01 |
| 1 | UPDATE | T1 | | | | |
|* 2 | TABLE ACCESS FULL| T1 | 1 | 4 | 6 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("ID"=100)
SQL> rollback;
Rollback complete.
SQL> update t2 set id=1000001 where id=100;
1 row updated.
Execution Plan
----------------------------------------------------------
Plan hash value: 3398718552
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | 5 | 2 (0)| 00:00:01 |
| 1 | UPDATE | T2 | | | | |
|* 2 | INDEX UNIQUE SCAN| SYS_C006532 | 1 | 5 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=100)
SQL> update /*+ full(t2) */ t2 set id=1000001 where id=100;
0 rows updated.
Execution Plan
----------------------------------------------------------
Plan hash value: 2722410703
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | 5 | 444 (7)| 00:00:06 |
| 1 | UPDATE | T2 | | | | |
|* 2 | TABLE ACCESS FULL| T2 | 1 | 5 | 444 (7)| 00:00:06 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("ID"=100)
SQL> rollback;
Rollback complete.
delete操作:
SQL> delete from t2 where id=100;
1 row deleted.
Execution Plan
----------------------------------------------------------
Plan hash value: 1328729220
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 5 | 2 (0)| 00:00:01 |
| 1 | DELETE | T2 | | | | |
|* 2 | INDEX UNIQUE SCAN| SYS_C006532 | 1 | 5 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=100)
SQL> delete /*+ full(t2) */ from t2 where id=100;
0 rows deleted.
Execution Plan
----------------------------------------------------------
Plan hash value: 1451993194
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 5 | 444 (7)| 00:00:06 |
| 1 | DELETE | T2 | | | | |
|* 2 | TABLE ACCESS FULL| T2 | 1 | 5 | 444 (7)| 00:00:06 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("ID"=100)
SQL> rollback;
Rollback complete.
注意:一定要where中用到索引列才能走索引:
SQL> update t2 set name='T11' where name='T2'; --沒有用到索引列是一定不會走索引的。
1000000 rows updated.
Execution Plan
----------------------------------------------------------
Plan hash value: 2722410703
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1013K| 2970K| 447 (8)| 00:00:06 |
| 1 | UPDATE | T2 | | | | |
|* 2 | TABLE ACCESS FULL| T2 | 1013K| 2970K| 447 (8)| 00:00:06 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("NAME"='T2')
SQL> update /*+ index(t2 SYS_C006532) */ t2 set name='T11' where name='T2'; --強制走索引代價巨大
1000000 rows updated.
Execution Plan
----------------------------------------------------------
Plan hash value: 1100077776
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1013K| 2970K| 3728 (2)| 00:00:45 |
| 1 | UPDATE | T2 | | | | |
|* 2 | TABLE ACCESS BY INDEX ROWID| T2 | 1013K| 2970K| 3728 (2)| 00:00:45 |
| 3 | INDEX FULL SCAN | SYS_C006532 | 1013K| | 1907 (2)| 00:00:23 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("NAME"='T2')
插入數據的PLAN
SQL> insert into t1 values(10001,'T11');
1 row created.
Execution Plan
----------------------------------------------------------
-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 | 6 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------
A 在HWM以下找連續的空間將數據插入
B 沒有找到,在HWM之上插入數據,後HWM上移。
-------------------------------------
塊中的行的分佈密度對使用索引的影響。
SQL> conn hr/hr
Connected.
SQL> create table t3(id int primary key,name1 varchar2(2000),name2 varchar2(2000)); --行密度大的表
Table created.
SQL> create table t4(id int primary key,name1 char(2000),name2 char(2000)); --行密度小的表
Table created.
塊大小是8K,預留10%的空間,實際每個塊能存7373個字節,T4表的塊只能放一行數據。
SQL> begin
2 for i in 1..20000 loop
3 insert into t3 values(i,'T3','T31');
4 end loop;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
SQL> begin
2 for i in 1..20000 loop
3 insert into t4 values(i,'T4','T41');
4 end loop;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_table_stats(user,'t3',estimate_percent=>100,cascade=>true);
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_table_stats(user,'t4',estimate_percent=>100,cascade=>true);
PL/SQL procedure successfully completed.
SQL> select * from t3 where id>17000;
Execution Plan
----------------------------------------------------------
Plan hash value: 4161002650
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3000 | 33000 | 14 (8)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T3 | 3000 | 33000 | 14 (8)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID">17000)
SQL> select * from t4 where id>17000; --行密度小的越容易用索引
Execution Plan
----------------------------------------------------------
Plan hash value: 1161789439
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3000 | 11M| 3011 (1)| 00:00:37 |
| 1 | TABLE ACCESS BY INDEX ROWID| T4 | 3000 | 11M| 3011 (1)| 00:00:37 |
|* 2 | INDEX RANGE SCAN | SYS_C006534 | 3000 | | 7 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID">17000)
SQL> set autotrace trace exp stat
SQL> select /*+ index(t3 SYS_C006533) */ * from t3 where id>17000;
3000 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 2289016736
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3000 | 33000 | 14 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T3 | 3000 | 33000 | 14 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | SYS_C006533 | 3000 | | 7 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID">17000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
415 consistent gets --走索引一致性讀還是有差別的
0 physical reads
0 redo size
55787 bytes sent via SQL*Net to client
2589 bytes received via SQL*Net from client
201 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
3000 rows processed
SQL> select * from t3 where id>17000;
3000 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 4161002650
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3000 | 33000 | 14 (8)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T3 | 3000 | 33000 | 14 (8)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID">17000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
253 consistent gets
0 physical reads
0 redo size
55787 bytes sent via SQL*Net to client
2589 bytes received via SQL*Net from client
201 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
3000 rows processed
T3表塊上行分佈密度比較大,用索引的概率小。T4表塊上行分佈密度小,用索引的概率大。
注意:上面這個實驗要找到臨界值才能成功的,臨界值就是返回就錄行數的值,
在這個值上走索引和全表掃的性能是一樣的。
------------------------------------------------------------------
案例:B樹索引使用的場合——鍵值重複率低的字段適合創建B樹索引
SQL> create table t5 as select object_id,object_name from all_objects;
Table created.
SQL> create table t6 as select mod(object_id,2) object_id,object_name from all_objects; --ID字段重複率很高
Table created.
SQL> create index t3_ind on t5(object_id);
Index created.
SQL> create index t6_ind on t6(object_id);
Index created.
SQL> select count(distinct object_id) from t5;
COUNT(DISTINCTOBJECT_ID)
------------------------
40929
SQL> select count(distinct object_id) from t6;
COUNT(DISTINCTOBJECT_ID)
------------------------
2
SQL> exec dbms_stats.gather_table_stats(user,'t5',estimate_percent=>100,cascade=>true);
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_table_stats(user,'t6',estimate_percent=>100,cascade=>true);
PL/SQL procedure successfully completed.
SQL> select * from t5 where object_id=1;
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 3812361271
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T5 | 1 | 30 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T3_IND | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=1)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
339 bytes sent via SQL*Net to client
389 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL> select * from t6 where object_id=1;
20511 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1930642322
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 20465 | 539K| 46 (3)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T6 | 20465 | 539K| 46 (3)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=1)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
1556 consistent gets
0 physical reads
0 redo size
626252 bytes sent via SQL*Net to client
15437 bytes received via SQL*Net from client
1369 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
20511 rows processed
強制T6走索引的話
SQL> select /*+ index(t6 T6_IND) */ * from t6 where object_id=1;
20511 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1497073299
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 20465 | 539K| 228 (1)| 00:00:03 |
| 1 | TABLE ACCESS BY INDEX ROWID| T6 | 20465 | 539K| 228 (1)| 00:00:03 |
|* 2 | INDEX RANGE SCAN | T6_IND | 20465 | | 40 (3)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=1)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2954 consistent gets
0 physical reads
0 redo size
626252 bytes sent via SQL*Net to client
15437 bytes received via SQL*Net from client
1369 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
20511 rows processed
oracle先要掃索引的葉子行,找到符合條件的鍵值,根據鍵值中的rowid到表中找到對應的行。
如果滿足的條件很多,oracle不停的訪問索引再訪問表,如此循環。
SQL> select object_id from t5 where object_id=1; --查詢索引列,不需要用rowid再去訪問表了,
因爲查詢索引已經滿足了要求。
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 2377336880
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| T3_IND | 1 | 5 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("OBJECT_ID"=1)
SQL> select object_id from t6 where object_id=1;
20511 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3707116216
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 20465 | 61395 | 20 (5)| 00:00:01 |
|* 1 | INDEX FAST FULL SCAN| T6_IND | 20465 | 61395 | 20 (5)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=1)
結論:創建索引的時候,要選擇那些鍵值重複率低的字段。否則是很難用上的。