轉載-Oracle全局索引和本地索引

文章出處:http://blog.csdn.net/tannafe/article/details/4132858

 Oracle索引分區雜談

Oracle數據庫中,有兩種類型的分區索引,全局索引和本地索引,其中本地索引又可以分爲本地前綴索引和本地非前綴索引。下面就分別看看每種類型的索引各自的特點。

全局索引以整個表的數據爲對象建立索引,索引分區中的索引條目既可能是基於相同的鍵值但是來自不同的分區,也可能是多個不同鍵值的組合。

全局索引既允許索引分區的鍵值和表分區鍵值相同,也可以不相同。全局索引和表之間沒有直接的聯繫,這一點和本地索引不同。

SQL> create table orders (
     order_no      number,
     part_no       varchar2(40),
     ord_date      date
     )
     partition by range (ord_date)
      (partition Q1 values less than (TO_DATE('01-APR-1999','DD-MON-YYYY')),
       partition Q2 values less than (TO_DATE('01-JUL-1999','DD-MON-YYYY')),
       partition Q3 values less than (TO_DATE('01-OCT-1999','DD-MON-YYYY')),
       partition Q4 values less than (TO_DATE('01-JAN-2000','DD-MON-YYYY'))
      )
     ;

Table created.

SQL> create index orders_global_1_idx
     on orders(ord_date)
      global partition by range (ord_date)
       (partition GLOBAL1 values less than (TO_DATE('01-APR-1999','DD-MON-YYYY')),
        partition GLOBAL2 values less than (TO_DATE('01-JUL-1999','DD-MON-YYYY')),
        partition GLOBAL3 values less than (TO_DATE('01-OCT-1999','DD-MON-YYYY')),
        partition GLOBAL4 values less than (MAXVALUE)
       )
     ;

Index created.

SQL> create index orders_global_2_idx
     on orders(part_no)
      global partition by range (part_no)
       (partition IND1 values less than (555555),
        partition IND2 values less than (MAXVALUE)
       )
     ;

Index created.

從上面的語句可以看出,全局索引和表沒有直接的關聯,必須顯式的指定maxvalue值。假如表中新加了分區,不會在全局索引中自動增加新的分區,必須手工添加相應的分區。

SQL> alter table orders add partition Q5 values less than (TO_DATE('01-APR-2000','DD-MON-YYYY'));

Table altered.

SQL> select TABLE_NAME, PARTITION_NAME from dba_tab_partitions where table_name='ORDERS';

TABLE_NAME                     PARTITION_NAME
------------------------------ ------------------------------
ORDERS                         Q1
ORDERS                         Q2
ORDERS                         Q3
ORDERS                         Q4
ORDERS                         Q5

SQL> select INDEX_NAME, PARTITION_NAME from dba_ind_partitions where index_name=upper('orders_global_1_idx');

INDEX_NAME                     PARTITION_NAME
------------------------------ ------------------------------
ORDERS_GLOBAL_1_IDX            GLOBAL1
ORDERS_GLOBAL_1_IDX            GLOBAL2
ORDERS_GLOBAL_1_IDX            GLOBAL3
ORDERS_GLOBAL_1_IDX            GLOBAL4

使用全局索引,索引鍵值必須和分區鍵值相同,這就是所謂的前綴索引。Oracle不支持非前綴的全局分區索引,如果需要建立非前綴分區索引,索引必須建成本地索引。

SQL> create index orders_global_2_idx
  2  on orders(part_no)
  3   global partition by range (order_no)
  4    (partition IND1 values less than (555555),
  5     partition IND2 values less than (MAXVALUE)
  6    )
  7  ;
 global partition by range (order_no)
                                    *
ERROR at line 3:
ORA-14038: GLOBAL partitioned index must be prefixed

接下來再來看看本地分區。

本地索引的分區和其對應的表分區數量相等,因此每個表分區都對應着相應的索引分區。使用本地索引,不需要指定分區範圍因爲索引對於表而言是本地的,當本地索引創建時,Oracle會自動爲表中的每個分區創建獨立的索引分區。

創建本地索引不必顯式的指定maxvalue值,因爲爲表新添加表分區時,會自動添加相應的索引分區。

create index orders_local_1_idx
on orders(ord_date)
 local
  (partition LOCAL1,
   partition LOCAL2,
   partition LOCAL3,
   partition LOCAL4
  )
;

Index created.

SQL> select INDEX_NAME, PARTITION_NAME from dba_ind_partitions where index_name=upper('orders_local_1_idx');

INDEX_NAME                     PARTITION_NAME
------------------------------ ------------------------------
ORDERS_LOCAL_1_IDX             LOCAL1
ORDERS_LOCAL_1_IDX             LOCAL2
ORDERS_LOCAL_1_IDX             LOCAL3
ORDERS_LOCAL_1_IDX             LOCAL4

SQL> alter table orders add partition Q5 values less than (TO_DATE('01-APR-2000','DD-MON-YYYY'));

Table altered.

SQL> select INDEX_NAME, PARTITION_NAME from dba_ind_partitions where index_name=upper('orders_local_1_idx');

INDEX_NAME                     PARTITION_NAME
------------------------------ ------------------------------
ORDERS_LOCAL_1_IDX             LOCAL1
ORDERS_LOCAL_1_IDX             LOCAL2
ORDERS_LOCAL_1_IDX             LOCAL3
ORDERS_LOCAL_1_IDX             LOCAL4
ORDERS_LOCAL_1_IDX             Q5

這裏系統已經自動以和表分區相同的名字自動創建了一個索引分區。同理,刪除表分區時相對應的索引分區也自動被刪除。

本地索引和全局索引還有一個顯著的差別,就是上面提到的,本地索引可以創建成本地非前綴型,而全局索引只能是前綴型。

SQL> create index orders_local_2_idx
     on orders(part_no)
      local
       (partition LOCAL1,
        partition LOCAL2,
        partition LOCAL3,
        partition LOCAL4)
     ;

Index created.

SQL> select INDEX_NAME, PARTITION_NAME, HIGH_VALUE from dba_ind_partitions
     where index_name=upper('orders_local_2_idx');

INDEX_NAME                     PARTITION_NAME                 HIGH_VALUE
------------------------------ ------------------------------ ---------------------------------------------------------
ORDERS_LOCAL_2_IDX             LOCAL1                         TO_DATE(' 1999-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 
                                                              'NLS_CALENDAR=GREGORIA'
ORDERS_LOCAL_2_IDX             LOCAL2                         TO_DATE(' 1999-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 
                                                              'NLS_CALENDAR=GREGORIA'
ORDERS_LOCAL_2_IDX             LOCAL3                         TO_DATE(' 1999-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
                                                              'NLS_CALENDAR=GREGORIA'
ORDERS_LOCAL_2_IDX             LOCAL4                         TO_DATE(' 2000-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
                                                              'NLS_CALENDAR=GREGORIA'

從上面的輸出可以看出,雖然索引的鍵值是part_no,但索引分區的鍵值仍然和表的分區鍵值相同,即ord_date,也即是所謂的非前綴型索引。

最後,再引用一個例子說明前綴索引和非前綴索引的應用。

假設有一個使用DATE列分區的大表。我們經常使用一個VARCHAR2列(VCOL)進行查詢,但這個列並不是表的分區鍵值。

有兩種可能的方法來訪問VCOL列的數據,一是建立基於VCOL列的本地非前綴索引,

               |                                         |
             -------                                   -------
            |       |         (10 more                |        |
Values:     A..     Z..   partitions here)            A..      Z.. 

另一種是建立基於VCOL列的全局索引,

                |                                         |
              -------                                   -------
             |       |         (10 more                |        |
Values:      A..     D..   partitions here)            T..      Z.. 

可以看出,如果能夠保證VCOL列值的唯一性,全局索引將會是最好的選擇。如果VCOL列值不唯一,就需要在本地非前綴索引的並行查詢和全局索引順序查詢以及高昂的維護代價之間做出選擇。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章