Oracle 反向索引(反轉建索引) 理解


  • 一 反向索引

    1.1 反向索引的定義

    • 反向索引作為B-tree索引的一個分支,主要是在創建索引時,針對索引列的索引鍵值進行字節反轉,進而實現分散存放到不同葉子節點塊的目的。

     

    1.2 反向索引針對的問題

    • 使用傳統的B-tree索引,當索引的列是按順序產生時,相應的索引鍵值會基本分布在同一個葉塊中。當用戶對該列進行操作時,難免會發生索引塊的爭用。
    • 使用反向索引,將索引列的鍵值進行反轉,實現順序的鍵值分散到不同的葉塊中,從而減少索引塊的爭用。
    • 例如:鍵值1001、1002、1003,反轉后1001、2001、3001,進而分散到不用的葉子節點塊中。

     

    1.3 反向索引應用場景

    • 索引塊成為熱點塊
    • rac環境
      • rac環境下中多節點訪問訪問數據呈現密集且集中的特點,索引熱塊的產生較高。
      • 在范圍檢索不高的rac環境中使用反向索引可有效提高性能。

     

    1.4 反向索引的優點與缺點

    • 優點:降低索引葉子塊的爭用問題,提升系統性能。
    • 缺點:對於范圍檢索,例如:between,>,<時,反向索引無法引用,進而導致全表掃面的產生,降低系統性能。

     

    1.5 反向索引示例說明

  • -- 創建兩張相同結構的表,內部結構及數據均引用scott用戶下的emp表SQL> select count(*) from test01;
    
      COUNT(*)
    ----------
    
    SQL> select count(*) from test02;
    
      COUNT(*)
    ----------
    
    
    
    --針對表TEST01的empno列,添加B-tree索引 
    SQL> create index PK_TEST01 on TEST01(EMPNO);
    Index created.
    
    --針對表TEST02的empno列,添加反向索引
    SQL> create index PK_REV_TEST02 on TEST02(EMPNO) REVERSE;
    Index created.
    
    
    --驗證上面的索引,NORMAL/REV表明為反向索引
    SQL> select TABLE_NAME,INDEX_NAME,INDEX_TYPE from user_indexes where INDEX_NAME like '%TEST%';
    
    TABLE_NAME           INDEX_NAME           INDEX_TYPE
    -------------------- -------------------- --------------------
    TEST01               PK_TEST01            NORMAL
    TEST02               PK_REV_TEST02        NORMAL/REV
    
    
    --打開會話追蹤
    SQL> set autotrace traceonly
    
    
    --相同條件查詢,觀察兩表的執行計划
    SQL> select * from TEST01 where empno=7369;
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 515586510
    
    -----------------------------------------------------------------------------------------
    | Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |           |     1 |    87 |     2   (0)| 00:00:01 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| TEST01    |     1 |    87 |     2   (0)| 00:00:01 |
    |*  2 |   INDEX RANGE SCAN          | PK_TEST01 |     1 |       |     1   (0)| 00:00:01 |
    -----------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    - access("EMPNO"=7369)
    
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    
    
    Statistics
    ----------------------------------------------------------
     recursive calls
     db block gets
     consistent gets
     physical reads
     redo size
     bytes sent via SQL*Net to client
     bytes received via SQL*Net from client
     SQL*Net roundtrips to/from client
     sorts (memory)
     sorts (disk)
     rows processed
    
    
    
    
    SQL> select * from TEST02 where empno=7369;
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 1053012716
    
    ---------------------------------------------------------------------------------------------
    | Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |               |     1 |    87 |     2   (0)| 00:00:01 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| TEST02        |     1 |    87 |     2   (0)| 00:00:01 |
    |*  2 |   INDEX RANGE SCAN          | PK_REV_TEST02 |     1 |       |     1   (0)| 00:00:01 |
    ---------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    - access("EMPNO"=7369)
    
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    
    
    Statistics
    ----------------------------------------------------------
     recursive calls
     db block gets
     consistent gets
     physical reads
     redo size
     bytes sent via SQL*Net to client
     bytes received via SQL*Net from client
     SQL*Net roundtrips to/from client
     sorts (memory)
     sorts (disk)
     rows processed
    
    
    
    
    -- 相同范圍條件查詢,觀察兩表的執行計划
    SQL> select * from TEST01 where empno between 7350 and 7500;
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 515586510
    
    -----------------------------------------------------------------------------------------
    | Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |           |     2 |   174 |     2   (0)| 00:00:01 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| TEST01    |     2 |   174 |     2   (0)| 00:00:01 |
    |*  2 |   INDEX RANGE SCAN          | PK_TEST01 |     2 |       |     1   (0)| 00:00:01 |
    -----------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    - access("EMPNO">=7350 AND "EMPNO"<=7500)
    
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    
    
    Statistics
    ----------------------------------------------------------
     recursive calls
     db block gets
     consistent gets
     physical reads
     redo size
     bytes sent via SQL*Net to client
     bytes received via SQL*Net from client
     SQL*Net roundtrips to/from client
     sorts (memory)
     sorts (disk)
     rows processed
    
    
    
    
    
    SQL> select * from TEST02 where empno between 7350 and 7500;
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 3294238222
    
    ----------------------------------------------------------------------------
    | Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |        |     2 |   174 |     3   (0)| 00:00:01 |
    |*  1 |  TABLE ACCESS FULL| TEST02 |     2 |   174 |     3   (0)| 00:00:01 |
    ----------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    - filter("EMPNO">=7350 AND "EMPNO"<=7500)
    
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    
    
    Statistics
    ----------------------------------------------------------
     recursive calls
     db block gets
     consistent gets0  redo size
     bytes sent via SQL*Net to client
     bytes received via SQL*Net from client
     SQL*Net roundtrips to/from client
     sorts (memory)
     sorts (disk)
     rows processed

    通過上面的示例可以看到,當使用between條件進行范圍查詢時,采用反向索引的表,並沒有使用索引,而是采用了全表掃面的方式進行檢索。


免責聲明!

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



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