分割槽表索引實踐案例

dbhelper發表於2015-03-01
  今天對分割槽表的索引(包括本地分割槽索引、全域性分割槽索引、非分割槽索引)進行試驗測試.
=================================================================================================
                                                                 分割槽索引基礎知識梳理
=================================================================================================
分割槽表的全域性索引圖示如下:

建立語法為:
CREATE [url=]INDEX[/url] INX_TAB_PARTITION_COL1 ON TABLE_PARTITION(COL1)
  GLOBAL PARTITION BY RANGE(COL1)
         PARTITION IDX_P1 values less than (1000000),
         PARTITION IDX_P2 values less than (2000000),
         PARTITION IDX_P3 values less than (MAXVALUE)
  )
LOCAL索引結構圖如下示:

建立語法為:
CREATE INDEX INX_TAB_PARTITION_COL1 ON TABLE_PARTITION(COL1) LOCAL;
也可按照分割槽表的的分割槽結構給與一一定義,索引的分割槽將得到重新命名。
分割槽上的點陣圖索引只能為LOCAL索引,不能為GLOBAL全域性索引。
=================================================================================================

分割槽索引分為本地(local index)索引和全域性索引(global index)。
---------------&gt>官方指南:

Local Partitioned Indexes

In a local partitioned index, the index is partitioned on the same columns, with the same number of partitions and the same partition bounds as its table. Each index partition is associated with exactly one partition of the underlying table, so that all keys in an index partition refer only to rows stored in a single table partition. In this way, the database automatically synchronizes index partitions with their associated table partitions, making each table-index pair independent.

Local partitioned indexes are common in data warehousing environments. Local indexes offer the following advantages:

  • Availability is increased because actions that make data invalid or unavailable in a partition affect this partition only.

  • Partition maintenance is simplified. When moving a table partition, or when data ages out of a partition, only the associated local index partition must be rebuilt or maintained. In a global index, all index partitions must be rebuilt or maintained.

  • If point-in-time recovery of a partition occurs, then the indexes can be recovered to the recovery time (see "Data File Recovery"). The entire index does not need to be rebuilt.

Example 4-4 shows the creation statement for the partitioned hash_sales table, using the prod_id column as partition key. Example 4-5 creates a local partitioned index on the time_id column of the hash_sales table.

Example 4-5 Local Partitioned Index

CREATE INDEX hash_sales_idx ON hash_sales(time_id) LOCAL;

In Figure 4-4, the hash_products table has two partitions, so hash_sales_idx has two partitions. Each index partition is associated with a different table partition. Index partition SYS_P38 indexes rows in table partition SYS_P33, whereas index partition SYS_P39 indexes rows in table partition SYS_P34.



------------------&gt>注意區別差異:

Global Partitioned Indexes

A global partitioned index is a B-tree index that is partitioned independently of the underlying table on which it is created. A single index partition can point to any or all table partitions, whereas in a locally partitioned index, a one-to-one parity exists between index partitions and table partitions.

In general, global indexes are useful for OLTP applications, where rapid access, data integrity, and availability are important. In an OLTP system, a table may be partitioned by one key, for example, the employees.department_id column, but an application may need to access the data with many different keys, for example, by employee_id or job_id. Global indexes can be useful in this scenario.

You can partition a global index by range or by hash. If partitioned by range, then the database partitions the global index on the ranges of values from the table columns you specify in the column list. If partitioned by hash, then the database assigns rows to the partitions using a hash function on values in the partitioning key columns.

As an illustration, suppose that you create a global partitioned index on the time_range_sales table from Example 4-2. In this table, rows for sales from 1998 are stored in one partition, rows for sales from 1999 are in another, and so on. Example 4-6 creates a global index partitioned by range on the channel_id column.

Example 4-6 Global Partitioned Index

CREATE INDEX time_channel_sales_idx ON time_range_sales (channel_id)
   GLOBAL PARTITION BY RANGE (channel_id)
      (PARTITION p1 VALUES LESS THAN (3),
       PARTITION p2 VALUES LESS THAN (4),
       PARTITION p3 VALUES LESS THAN (MAXVALUE));

As shown in Figure 4-5, a global index partition can contain entries that point to multiple table partitions. Index partition p1 points to the rows with a channel_id of 2, index partition p2 points to the rows with a channel_id of 3, and index partition p3 points to the rows with a channel_id of 4 or 9.



其中本地索引又可以分為有字首(prefix)的索引和無字首(nonprefix)的索引。而全域性索引目前只支援有字首的索引。B樹索引和點陣圖索引都可以分割槽,但是HASH索引不可以被分割槽。點陣圖索引必須是本地索引。

一:本地索引:建立了一個分割槽表後,如果需要在表上面建立索引,並且索引的分割槽機制和表的分割槽機制一樣,那麼這樣的索引就叫做本地分割槽索引。本地索引是由ORACLE自動管理的,它分為有字首的本地索引和無字首的本地索引。什麼叫有字首的本地索引?有字首的本地索引就是包含了分割槽鍵,並且將其作為引導列的索引。什麼叫無字首的本地索引?無字首的本地索引就是沒有將分割槽鍵的前導列作為索引的前導列的索引

二:全域性索引:與本地分割槽索引不同的是,全域性分割槽索引的分割槽機制與表的分割槽機制不一樣。全域性分割槽索引全域性分割槽索引只能是B樹索引,到目前為止(10gR2),oracle只支援有字首的全域性索引。另外oracle不會自動的維護全域性分割槽索引,當我們在對錶的分割槽做修改之後,如果執行修改的語句不加上update global indexes的話,那麼索引將不可用;
三:分割槽索引不能夠將其作為整體重建,必須對每個分割槽重建

=================================================================================================
                                                                  建立分割槽表並插入資料
=================================================================================================
--建立基於日期的範圍分割槽,分割槽子句未指定表空間時則位於預設的表空間
create table sal_range   
            (salesman_id number(5),
            salesman_name varchar2(30),
            sales_date date)
            partition by range (sales_date) 
            (
            partition sal_jan2000 values less than(to_date('2014-02-01',
                'YYYY-MM-DD')),
            partition sal_feb2000 values less than(to_date('2014-03-01',
                'YYYY-MM-DD')),
            partition sal_mar2000 values less than(to_date('2014-04-01',
                'YYYY-MM-DD')),
            partition pmax values less than(maxvalue)
            );
--建立本地分割槽索引
create index sal_range_index_local on sal_range(sales_date) local
(
partition sal_jan2000_index,
partition sal_feb2000_index,
partition sal_mar2000_index,
partition pmax_index
);
--插入資料
begin
for i in 1 .. 10 loop
insert into sal_range values(i,'sal_name'||i,to_date('2013-12-31','YYYY-MM-DD')+i);
end loop;
commit;
end; 

begin
for i in 1 .. 10 loop
insert into sal_range values(i+10,'sal_name'||(i+10),to_date('2014-01-31','YYYY-MM-DD')+i);
end loop;
commit;
end; 

begin
for i in 1 .. 10 loop
insert into sal_range values(i+20,'sal_name'||(i+20),to_date('2014-02-28','YYYY-MM-DD')+i);
end loop;
commit;
end; 
 
begin
for i in 1 .. 10 loop
insert into sal_range values(i+30,'sal_name'||(i+30),to_date('2014-04-30','YYYY-MM-DD')+i);
end loop;
commit;
end; 

begin
for i in 1 .. 10 loop
insert into sal_range values(i+40,'sal_name'||(i+40),to_date('2014-03-31','YYYY-MM-DD')+i);
end loop;
commit;
end;

begin
for i in 1 .. 10 loop
insert into sal_range values(i+50,'sal_name'||(i+50),to_date('2014-04-30','YYYY-MM-DD')+i);
end loop;
commit;
end;

begin
for i in 1 .. 10 loop
insert into sal_range values(i+60,'sal_name'||(i+60),to_date('2014-05-31','YYYY-MM-DD')+i);
end loop;
commit;
end;

begin
for i in 1 .. 10 loop
insert into sal_range values(i+70,'sal_name'||(i+70),to_date('2014-06-30','YYYY-MM-DD')+i);
end loop;
commit;
end;

begin
for i in 1 .. 10 loop
insert into sal_range values(i+80,'sal_name'||(i+80),to_date('2014-07-31','YYYY-MM-DD')+i);
end loop;
commit;
end;

---查詢測試
SQL> select * from sal_range partition(sal_jan2000);
 
SALESMAN_ID SALESMAN_NAME                  SALES_DATE
----------- ------------------------------ -----------
          1 sal_name1                      2014-1-1
          2 sal_name2                      2014-1-2
          3 sal_name3                      2014-1-3
          4 sal_name4                      2014-1-4
          5 sal_name5                      2014-1-5
          6 sal_name6                      2014-1-6
          7 sal_name7                      2014-1-7
          8 sal_name8                      2014-1-8
          9 sal_name9                      2014-1-9
         10 sal_name10                     2014-1-10
 
SQL> select * from sal_range partition(sal_feb2000);
 
SALESMAN_ID SALESMAN_NAME                  SALES_DATE
----------- ------------------------------ -----------
         11 sal_name11                     2014-2-1
         12 sal_name12                     2014-2-2
         13 sal_name13                     2014-2-3
         14 sal_name14                     2014-2-4
         15 sal_name15                     2014-2-5
         16 sal_name16                     2014-2-6
         17 sal_name17                     2014-2-7
         18 sal_name18                     2014-2-8
         19 sal_name19                     2014-2-9
         20 sal_name20                     2014-2-10

======================================================================
--建立基於值範圍的分割槽,分割槽子句未指定表空間時則位於預設的表空間(此表不作為試驗表,只是簡單實現對比) 
            create table num_range      
            (num_id number,ename varchar2(50))
            partition by range (num_id)
            (
                partition p1 values less than (10),
                partition p2 values less than (20),
                partition p3 values less than (30),
                partition p4 values less than (maxvalue)
            );
--插入資料
begin
for i in 1 .. 30 loop
insert into num_range values(i,'num_range'||i);
end loop;
commit;
end;
--查詢
select * from num_range;
select * from num_range partition(p1);
=============================================================================
                                              建立全域性分割槽索引
 =============================================================================

--建立分割槽索引(只有在分割槽表上才可以)
create index num_range_index on num_range(num_id) local;
--建立本地分割槽的唯一索引時,索引必須包括分割槽列
create unique index num_range_uniq_index on num_range(num_id,ename) local;
--建立本地分割槽索引
create index sal_range_index_global on sal_range(salesman_id) global
partition by range(salesman_id)
(
partition sal_range_10 values less than(11),
partition sal_range_20 values less than(31),
partition sal_range_30 values less than(41),
partition sal_range_max values less than(maxvalue)
);
SQL> select partition_name,status from user_ind_partitions where index_name='SAL_RANGE_INDEX_GLOBAL';
 
PARTITION_NAME                 STATUS
------------------------------ --------
SAL_RANGE_10                   USABLE
SAL_RANGE_20                   USABLE
SAL_RANGE_30                   USABLE
SAL_RANGE_MAX                  USABLE

===================================================================================
                                                       建立本地分割槽索引
 ===================================================================================
全域性分割槽索引實質上意味著該索引與資料表有不同的分割槽方案,且是基於分割槽表的一個或一組列進行分割槽的。主要是為了提高資料庫中的資料查詢 的效能.
create index sal_range_index_local on sal_range(sales_date) local
(
partition sal_jan2000_index,
partition sal_feb2000_index,
partition sal_mar2000_index,
partition pmax_index
);
--查詢

SQL> select partition_name,status from user_ind_partitions where index_name='SAL_RANGE_INDEX_GLOBAL';
 
PARTITION_NAME                 STATUS
------------------------------ --------
SAL_RANGE_10                   USABLE
SAL_RANGE_20                   USABLE
SAL_RANGE_30                   USABLE
SAL_RANGE_MAX                  USABLE
--注意:刪除全域性分割槽索引的部分分割槽後,如果被包含分割槽包含索引條目,上限比它高的相鄰分割槽將被標記為不可用,且必須為索引指定一個maxvalue,這樣就能保證新插入的資料將在全域性分割槽索引中有地方儲存,否則會報錯如下:
----&gt>
SQL 錯誤: ORA-14021: 必須指定所有列的 MAXVALUE
14021. 00000 -  "MAXVALUE must be specified for all columns"
*Cause:    In the VALUES LESS THAN clause for the highest (last) partition
           of a GLOBAL index, MAXVALUE must be specified for all columns
*Action:   Ensure that VALUES LESS THAN clause for the last partition of a
           GLOBAL index has MAXVALUE specified for all columns

alter index sal_range_index_global drop partition sal_range_20;

--查詢
SQL> select partition_name,status from user_ind_partitions where index_name='SAL_RANGE_INDEX_GLOBAL';
 
PARTITION_NAME                 STATUS
------------------------------ --------
SAL_RANGE_10                   USABLE
SAL_RANGE_30                   UNUSABLE
SAL_RANGE_MAX                  USABLE

===================================================================================
                                                維護分割槽表的索引
===================================================================================
(1)新增分割槽:
alter table sal_range drop partition pmax;
alter table sal_range add partition sal_apr2000 values less than(to_date('2014-05-01','YYYY-MM-DD'));
--插入201404資料
begin
for i in 1 .. 10 loop
insert into sal_range values(i+40,'sal_name'||(i+40),to_date('2014-03-31','YYYY-MM-DD')+i);
end loop;
commit;
end;
--新增分割槽後確定操作對錶上索引的影響:
-----&gt>不影響本地分割槽索引、全域性分割槽索引和非分割槽索引
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                               PARTITION_NAME               STATUS
------------------------------                   ------------------------------           --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                    USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                    USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                    USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                  USABLE
SAL_RANGE_INDEX_LOCAL           SAL_APR2000                        USABLE
SAL_RANGE_INDEX_LOCAL           SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL           SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL           SAL_MAR2000_INDEX             USABLE

(2)截斷分割槽[不影響本地分割槽索引,非分割槽索引和全域性分割槽索引均會標記為UNUSABLE]:
alter table sal_range truncate partition(sal_apr2000);
----&gt>
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                UNUSABLE
SAL_RANGE_INDEX_LOCAL          SAL_APR2000                       USABLE
SAL_RANGE_INDEX_LOCAL          SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAR2000_INDEX              USABLE

(3)移動分割槽:
alter table sal_range move partition sal_apr2000 tablespace dawn;
---&gt>被移動本地分割槽索引UNUSABLE,非分割槽索引和全域性分割槽索引均會標記為UNUSABLE
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                  UNUSABLE
SAL_RANGE_INDEX_LOCAL          SAL_APR2000                    UNUSABLE
SAL_RANGE_INDEX_LOCAL          SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAR2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAY2000                    USABLE

(4)拆分分割槽[拆分分割槽最常見的原因是,需要簡單新增一個分割槽,而它不是表最高階的分割槽,所以由拆分來實現,面不是新增分割槽來實現。由於新的分割槽以前不存在,就沒有分割槽索引與之對應,所狀態為UNUSABLE,其他分割槽狀態正常,非分割槽索引和全域性分割槽索引也會變為UNUSABLE]:
----&gt>
alter table sal_range add partition pmax values less than(maxvalue);
----&gt>
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                  UNUSABLE
SAL_RANGE_INDEX_LOCAL          PMAX                           USABLE
SAL_RANGE_INDEX_LOCAL          SAL_APR2000                    UNUSABLE
SAL_RANGE_INDEX_LOCAL          SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAR2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAY2000                    USABLE
--先修復索引再進行拆分試驗(本地分割槽索引rebuild,全域性分割槽索引recreate):
alter index SAL_RANGE_INDEX_LOCAL rebuild partition SAL_APR2000;

alter table sal_range drop partition pmax;
create index sal_range_index_global on sal_range(salesman_id) global
partition by range(salesman_id)
(
partition sal_range_10 values less than(11),
partition sal_range_20 values less than(31),
partition sal_range_30 values less than(41),
partition sal_range_max values less than(maxvalue)
);
------&gt>所有索引狀態正常:
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                   USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                   USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                   USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                  USABLE
SAL_RANGE_INDEX_LOCAL          PMAX                           USABLE
SAL_RANGE_INDEX_LOCAL          SAL_APR2000                    USABLE
SAL_RANGE_INDEX_LOCAL          SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAR2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAY2000                    USABLE
----&gt>索引拆分(這裡需要注意,只有新拆分的分割槽中有資料時狀態才會是UNUSABLE):
alter table sal_range split partition PMAX at(to_date('2014-07-01','YYYY-MM-DD')) into(partition sal_june2000,partition pmax);
----&gt>
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                 UNUSABLE
SAL_RANGE_INDEX_LOCAL          PMAX                              UNUSABLE
SAL_RANGE_INDEX_LOCAL          SAL_APR2000                       USABLE
SAL_RANGE_INDEX_LOCAL          SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JUNE2000                 UNUSABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAR2000_INDEX             USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAY2000                       USABLE

(5)交換分割槽(被交換分割槽狀態變為UNUSABLE,全域性分割槽索引和非分割槽索引均變為UNUSABLE):
---&gt>先建立分割槽交換表(sal_range_exch)
create table sal_range_exch(salesman_id number(5),
            salesman_name varchar2(30),
            sales_date date);
--交換分割槽

alter table sal_range exchange partition sal_june2000 with table sal_range_exch;
---&gt>分割槽交換後表索引資訊:
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                  UNUSABLE
SAL_RANGE_INDEX_LOCAL          PMAX                                    USABLE
SAL_RANGE_INDEX_LOCAL          SAL_APR2000                       USABLE
SAL_RANGE_INDEX_LOCAL          SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JUNE2000                      UNUSABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAR2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAY2000                       USABLE

--&gt>校驗交換效果

SQL> select * from sal_range_exch;
 
SALESMAN_ID SALESMAN_NAME                  SALES_DATE
----------- ------------------------------ -----------
         61 sal_name61                     2014-6-1
         62 sal_name62                     2014-6-2
         63 sal_name63                     2014-6-3
         64 sal_name64                     2014-6-4
         65 sal_name65                     2014-6-5
         66 sal_name66                     2014-6-6
         67 sal_name67                     2014-6-7
         68 sal_name68                     2014-6-8
         69 sal_name69                     2014-6-9
         70 sal_name70                     2014-6-10

(6)刪除分割槽(對其他本地分割槽索引有沒影響,但全域性分割槽索引和非分割槽索引狀態均變為UNUSABLE):
---&gt>刪除前先修復所有分割槽正常:
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                   USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                   USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                   USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                  USABLE
SAL_RANGE_INDEX_LOCAL          PMAX                           USABLE
SAL_RANGE_INDEX_LOCAL          SAL_APR2000                    USABLE
SAL_RANGE_INDEX_LOCAL          SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JUNE2000                   USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAR2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAY2000                    USABLE
---&gt>刪除分割槽pmax後分割槽索引明細:
alter table sal_range drop partition pmax;
-----&gt>
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                  UNUSABLE
SAL_RANGE_INDEX_LOCAL          SAL_APR2000                    USABLE
SAL_RANGE_INDEX_LOCAL          SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JUNE2000                   USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAR2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAY2000                    USABLE

(7)合併分割槽:

---&gt>前期分割槽情況:
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                   USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                   USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                   USABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                  USABLE
SAL_RANGE_INDEX_LOCAL          PMAX                           USABLE
SAL_RANGE_INDEX_LOCAL          SAL_APR2000                    USABLE
SAL_RANGE_INDEX_LOCAL          SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JULY2000                   UNUSABLE
SAL_RANGE_INDEX_LOCAL          SAL_JUNE2000                   USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAR2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAY2000                    USABLE
---&gt>合併七月分割槽和max為max分割槽:
alter table sal_range merge partitions sal_july2000,pmax into partition pmax;
---&gt>操作用分割槽明細:
SQL> select t1.index_name,t1.partition_name,t1.status from user_ind_partitions t1 where t1.index_name in (
  2  select index_name from user_indexes t2 where t2.table_name='SAL_RANGE')order by 1,2,3;
 
INDEX_NAME                     PARTITION_NAME                 STATUS
------------------------------ ------------------------------ --------
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_10                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_20                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_30                   UNUSABLE
SAL_RANGE_INDEX_GLOBAL         SAL_RANGE_MAX                  UNUSABLE
SAL_RANGE_INDEX_LOCAL          PMAX                           UNUSABLE
SAL_RANGE_INDEX_LOCAL          SAL_APR2000                    USABLE
SAL_RANGE_INDEX_LOCAL          SAL_FEB2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JAN2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_JUNE2000                   USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAR2000_INDEX              USABLE
SAL_RANGE_INDEX_LOCAL          SAL_MAY2000                    USABLE
==================================================================================
                                    注意事項
===================================================================================
a1.查詢user_indexes檢視時,分割槽索引對應的狀態是N/A(表示不可用)。只有基於索引分割槽最精細的資料字典檢視(user_ind_partitions)的狀態才會填入資料,如果查詢的是子分割槽
   索引,則需查詢user_ind_subpartitions;
-------------------&gt>因為以前在這塊東西曾經給我帶來了不少麻煩,痛定思痛,總結如下,防患於未然,希望能幫到相關學友:

圖1
註解:IDX_R_CAR_ALARM_STAT_MONTH和IDX_R_CAR_ALL_BASIC_MONTH是單分割槽表索引,中status值為:N/A,其餘status值為N/A的都是複合分割槽表索引。
      在user_indexes中分割槽表索引狀態均為N/A,只代表索引有效,並不能代表其是否正常
========================================================================================================

圖2
註解:IDX_R_CAR_ALARM_STAT_MONTH和IDX_R_CAR_ALL_BASIC_MONTH是單分割槽表索引,在user_ind_partitions中status值才會正常表示,複合分割槽表索引均為N/A
========================================================================================================

圖3
註解:複合分割槽表索引status 只能在user_ind_subpartitions中查詢,非分割槽索引和單分割槽索引根本就不會在這資料字典裡顯示.
======================================================================================================

a2.以上分割槽索引維護的各步試驗過是先將全域性索引先drop再create,本地分割槽索引採用類似alter index SAL_RANGE_INDEX_LOCAL rebuild partition pmax的指令碼處理後再進行後     續試驗.;
a3.oracle對於本地分割槽索引的建立,如果建立分割槽,那麼所有分割槽都會建立相應分割槽索引,即使你建立本地分割槽索引時指定的索引分割槽個小小於表真實分割槽個數,比如我的本地建立分割槽索引過程(只列舉了四個分割槽,實際是有7個)。
create index sal_range_index_local on sal_range(sales_date) local
(
partition sal_jan2000_index,
partition sal_feb2000_index,
partition sal_mar2000_index,
partition pmax_index
);
如果採用簡單方法類似:
create index sal_range_index_local on sal_range(hire_date) tablespace dawn local.那麼產生的索引分割槽名和表分割槽名預設是一樣的.

最後,關於分割槽表的相關試驗案例請參考:http://blog.itpub.net/29119536/viewspace-1142363/
        關於分割槽表的基礎知識請參考:http://blog.itpub.net/29119536/viewspace-1141934/

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29119536/viewspace-1145136/,如需轉載,請註明出處,否則將追究法律責任。

相關文章