Oracle索引梳理系列(二)- Oracle索引種類及B樹索引


版權聲明:本文發布於http://www.cnblogs.com/yumiko/,版權由Yumiko_sunny所有,歡迎轉載。轉載時,請在文章明顯位置注明原文鏈接。若在未經作者同意的情況下,將本文內容用於商業用途,將保留追究其法律責任的權利。如果有問題,請以郵箱方式聯系作者(793113046@qq.com)。


 

Oracle索引種類

一 Oracle索引類型概述

oracle索引的種類主要有以下幾種:

  1. B樹索引:oracle默認的索引類型,內部采用二叉樹結構,根據rowid實現訪問行的快速定位。
  2. 反向索引:反轉B樹索引的索引列的鍵值字節,尤其是索引列值遞增且批量插入數據時,使索引分布均勻。
  3. 位圖索引:通過使用位圖,標識被索引的列值,進而管理與數據行的對應關系。主要用於OLAP的系統。
  4. 表簇索引:使用表簇索引必須要使用表簇(cluster)。
  5. 函數索引:通過函數將數據列計算的返回值作為索引鍵值建立的索引結構。

 


 

二 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),訪問數據塊,進而取得結果。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM