版權聲明:本文發布於http://www.cnblogs.com/yumiko/,版權由Yumiko_sunny所有,歡迎轉載。轉載時,請在文章明顯位置注明原文鏈接。若在未經作者同意的情況下,將本文內容用於商業用途,將保留追究其法律責任的權利。如果有問題,請以郵箱方式聯系作者(793113046@qq.com)。
Oracle索引種類
一 Oracle索引類型概述
oracle索引的種類主要有以下幾種:
- B樹索引:oracle默認的索引類型,內部采用二叉樹結構,根據rowid實現訪問行的快速定位。
- 反向索引:反轉B樹索引的索引列的鍵值字節,尤其是索引列值遞增且批量插入數據時,使索引分布均勻。
- 位圖索引:通過使用位圖,標識被索引的列值,進而管理與數據行的對應關系。主要用於OLAP的系統。
- 表簇索引:使用表簇索引必須要使用表簇(cluster)。
- 函數索引:通過函數將數據列計算的返回值作為索引鍵值建立的索引結構。
二 B樹索引
2.1 B樹索引結構圖說明
- 該結構圖源自於網絡,從圖中不難看出,B樹索引結構主要由三部分組成:根節點、分支節點、葉子節點。
- 對於oracle而言,索引的層級號采用倒序的方式,既對於層級數為N的索引,根節點的層級號為N,其下一層的分支節點為N-1,類推。
- 需要注意的是,oracle會自動為表的主鍵列創建索引。
- 需要注意的是,oracle不會對包含NULL值的索引列進行索引;但對於組合索引,其中包含NULL值的,這一行會索引。
- 需要注意的是,索引發生的I/O次數與索引樹的層數成正比,因此有些情況下,采用“反向索引”(后面介紹),可以有效降低層數,今兒優化索引性能。
2.2 B樹索引說明 - 分支節點(包含根節點)
- 對於分支節點塊而言,其內部的索引條目采用順序排列,默認為升序,創建時也可制定為降序。
- 對於分支節點塊的索引條目而言,主要兩個字段:
- 該分支節點塊下面索引塊的最小鍵值。
- 鏈接的索引塊地址,該地址指向下面一個索引塊。
- 對於分支節點塊的索引條目數量,其大小由數據塊大小以及鍵值長度決定。
2.3 B樹索引說明 - 葉子節點
- 對於葉子節點塊而言,其內部的索引條目同樣采用順序排列,默認為升序,創建時可制定為降序 對於葉子節點塊的索引條目而言,同樣主要包含兩個字段:
- 索引的鍵值。對於單一列索引,其鍵值為一個列值;對於組合列索引,其鍵值為多個列值的組合。
- 鍵值的rowid信息。該rowid信息記錄表中的相應數據的物理地址。
- 對於葉子節點塊間的關系,采用雙向鏈表,包含了指向上一個葉子節點以及下一個葉子節點的指針,方便一定范圍內索引。
2.4 B樹索引的實際運用情況
- 檢索的數據列是索引指定列時,只需訪問索引塊即可完成數據的訪問
-
--查看表中的索引信息
Yumiko@sunny >select index_name,table_name,column_name from user_ind_columns where table_name = 'EMP'; INDEX_NAME TABLE_NAME COLUMN_NAME -------------------- -------------------- -------------------- PK_EMP EMP EMPNO--查看索引的類型,normal說明為正常B樹索引
Yumiko@sunny >select INDEX_NAME,TABLE_NAME,index_TYPE from user_indexes where index_name ='PK_EMP';
INDEX_NAME TABLE_NAME INDEX_TYPE
----------------------------------------------------
PK_EMP EMP NORMAL
--打開會話追蹤 Yumiko@sunny >set autotrace traceonly
--查看執行結果 Yumiko@sunny >select empno from emp where empno=7900; Execution Plan ---------------------------------------------------------- Plan hash value: 56244932 ---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 4 | 0 (0)| 00:00:01 | |* 1 | INDEX UNIQUE SCAN| PK_EMP | 1 | 4 | 0 (0)| 00:00:01 | ---------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("EMPNO"=7900) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 1 consistent gets 0 physical reads 0 redo size 523 bytes sent via SQL*Net to client 523 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed通過上面的執行計划可以看到,檢索數據僅僅掃描索引塊便返回數據,並未進一步通過rowid進行表的掃描(
TABLE
ACCESS
BY
INDEX
ROWID
)
- 檢索的數據列中,含有未涵蓋的索引指定列的時候,將會訪問索引塊以及數據塊進行數據的檢索
-
Yumiko@sunny >select index_name,table_name,column_name from user_ind_columns where table_name = 'EMP'; INDEX_NAME TABLE_NAME COLUMN_NAME -------------------- -------------------- -------------------- PK_EMP EMP EMPNO
Yumiko@sunny >select INDEX_NAME,TABLE_NAME,index_TYPE from user_indexes where index_name ='PK_EMP';
INDEX_NAME TABLE_NAME INDEX_TYPE
----------------------------------------------------
PK_EMP EMP NORMAL
Yumiko@sunny >set autotrace traceonly
Yumiko@sunny >select * from emp where empno=7900; Execution Plan ---------------------------------------------------------- Plan hash value: 2949544139 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 38 | 1 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 38 | 1 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN | PK_EMP | 1 | | 0 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("EMPNO"=7900) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 2 consistent gets 0 physical reads 0 redo size 889 bytes sent via SQL*Net to client 512 bytes received via SQL*Net from client 1 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed通過上面的執行計划可以看到,檢索數據在掃描索引塊后,進一步通過rowid進行表數據的掃描(
TABLE
ACCESS
BY
INDEX
ROWID
)
- 檢索數據時,當直接訪問表數據的成本(訪問數據塊)優於使用索引訪問表數據的成本(訪問索引塊+數據塊)時,將不使用索引掃描。如全表掃描。
-
Yumiko@sunny >select index_name,table_name,column_name from user_ind_columns where table_name = 'EMP'; INDEX_NAME TABLE_NAME COLUMN_NAME -------------------- -------------------- -------------------- PK_EMP EMP EMPNO
Yumiko@sunny >select INDEX_NAME,TABLE_NAME,index_TYPE from user_indexes where index_name ='PK_EMP';
INDEX_NAME TABLE_NAME INDEX_TYPE
----------------------------------------------------
PK_EMP EMP NORMAL
Yumiko@sunny >set autotrace traceonly Yumiko@sunny >select * from emp; 14 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 3956160932 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 532 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| EMP | 14 | 532 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 8 consistent gets 0 physical reads 0 redo size 1630 bytes sent via SQL*Net to client 523 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 14 rows processed通過上面的執行計划可以看到,當檢索全表時,並未進行索引掃描,而是采用全表掃描的方式(TABLE ACCESS FULL),訪問數據塊,進而取得結果。