【三思筆記】 全面學習Oracle分割槽表及分割槽索引

lhrbest發表於2017-07-22

[三思筆記]全面學習Oracle分割槽表及分割槽索引

2008-04-15

關於分割槽表和分割槽索引(About PartitionedTables and Indexes)

對於 10gR2 而言,基本上可以分成幾類:

v  Range(範圍)分割槽

v  Hash(雜湊)分割槽

v  List(列表)分割槽

v  以及組合分割槽:Range-Hash,Range-List

對於表而言(常規意義上的堆組織表),上述分割槽形式都可以應用(甚至可以對某個分割槽指定 compress 屬性),只不過分割槽依賴列不能是 lob,long 之類資料型別,每個表的分割槽或子分割槽數的總數不能超過 1024K-1 個。

對於索引組織表,只能夠支援普通分割槽方式,不支援組合分割槽,常規表的限制對於索引組織表同樣有效,除此之外呢,還有一些其實的限制,比如要求索引組織表的分割槽依賴列必須是主鍵才可以等。

注:本篇所有示例僅針對常規表,即堆組織表!

對於索引,需要區分建立的是全域性索引,或本地索引:

l   全域性索引(global index):即可以分割槽,也可以不分割槽。即可以建 range 分割槽,也可以建 hash 分割槽,即可建於分割槽表,又可建立於非分割槽表上,就是說,全域性索引是完全獨立的,因此它也需要我們更多的維護操作。

l   本地索引(local index):其分割槽形式與表的分割槽完全相同,依賴列相同,儲存屬性也相同。對於本地索引,其索引分割槽的維護自動進行,就是說你 add/drop/split/truncate 表的分割槽時,本地索引會自動維護其索引分割槽。

Oracle 建議如果單個表超過 2G 就最好對其進行分割槽,對於大表建立分割槽的好處是顯而易見的,這裡不多論述 why,而將重點放在 when 以及 how

WHEN

一、When 使用 Range 分割槽

Range 分割槽呢是應用範圍比較廣的表分割槽方式,它是以列的值的範圍來做為分割槽的劃分條件,將記錄存放到列值所在的 range 分割槽中,比如按照時間劃分,2008 1 季度的資料放到 a 分割槽,08 2 季度的資料放到 b 分割槽,因此在建立的時候呢,需要你指定基於的列,以及分割槽的範圍值,如果某些記錄暫無法預測範圍,可以建立 maxvalue 分割槽,所有不在指定範圍內的記錄都會被儲存到 maxvalue 所在分割槽中,並且支援指定多列做為依賴列,後面在講 how 的時候會詳細談到。

二、When 使用 Hash 分割槽

通常呢,對於那些無法有效劃分範圍的表,可以使用 hash 分割槽,這樣對於提高效能還是會有一定的幫助。 hash 分割槽會將表中的資料平均分配到你指定的幾個分割槽中,列所在分割槽是依據分割槽列的 hash 值自動分配,因此你並不能控制也不知道哪條記錄會被放到哪個分割槽中,hash 分割槽也可以支援多個依賴列。

三、When 使用 List 分割槽

List 分割槽與 range 分割槽和 hash 分割槽都有類似之處,該分割槽與 range 分割槽類似的是也需要你指定列的值,但這又不同與 range 分割槽的範圍式列值---其分割槽值必須明確指定,也不同與 hash 分割槽---透過明確指定分割槽值,你能控制記錄儲存在哪個分割槽。它的分割槽列只能有一個,而不能像 range 或者 hash 分割槽那樣同時指定多個列做為分割槽依賴列,不過呢,它的單個分割槽對應值可以是多個。你在分割槽時必須確定分割槽列可能存在的值,一旦插入的列值不在分割槽範圍內,則插入/更新就會失敗,因此通常建議使用list 分割槽時,要建立一個default 分割槽儲存那些不在指定範圍內的記錄,類似range 分割槽中的 maxvalue 分割槽。

四、When 使用組合分割槽

如果某表按照某列分割槽之後,仍然較大,或者是一些其它的需求,還可以透過分割槽內再建子分割槽的方式將分割槽再分割槽,即組合分割槽的方式。

組合分割槽呢在 10g 中有兩種:range-hashrange-list。注意順序喲,根分割槽只能是 range 分割槽,子分割槽可以是 hash 分割槽或 list 分割槽。

提示:11g 在組合分割槽功能這塊有所增強,又推出了 range-range,list-range,list-list,list-hash,這就相當於除 hash 外三種分割槽方式的笛卡爾形式都有了。為什麼會沒有 hash 做為根分割槽的組合分割槽形式呢,再仔細回味一下第二點,你一定能夠想明白~~

HOW

一、如何建立

 
  clip_image002


如果想對某個表做分割槽,必須在建立表時就指定分割槽,我們可以對一個包含分割槽的表中的分割槽做修改,但不能直接將一個未分割槽的表修改成分割槽表(起碼在 10g 是不行的,當然你可能會說,可以透過線上重定義的方式,但是這不是直接喲,這也是藉助臨時表間接實現的)

建立表或索引的語法就不說了,大家肯定比我還熟悉,而想在建表(索引)同時指定分割槽也非常容易,只需要把建立分割槽的子句放到";"前就行啦,同時需要注意表的 row movement 屬性,它用來控制是否允許修改列值所造成的記錄移動至其它分割槽儲存,有 enable|disable 兩種狀態,預設是 disable row movement,當 disable 時,如果記錄要被更新至其它分割槽,則更新語句會報錯。

下面分別演示不同分割槽方式的表和索引的建立:

1、建立 range 分割槽

語法如下,圖:[range_partitioning.gif]

需要我們指定的有:

l   column:分割槽依賴列(如果是多個,以逗號分隔);

l   partition:分割槽名稱;

l   values less than:後跟分割槽範圍值(如果依賴列有多個,範圍對應值也應是多個,中間以逗號分隔);

l   tablespace_clause:分割槽的儲存屬性,例如所在表空間等屬性(可為空),預設繼承基表所在表空間的屬性。

   建立一個標準的 range 分割槽表:

JSSWEB> create table t_partition_range (id number,name varchar2(50))

2    partition by range(id)(

3    partition t_range_p1 values less than (10) tablespace tbspart01,

4    partition t_range_p2 values less than (20) tablespace tbspart02, 5partition t_range_p3 values less than (30) tablespace tbspart03,

6       partition t_range_pmax values less than (maxvalue) tablespace tbspart04

7       );

表已建立。

要查詢建立分割槽的資訊,可以透過查詢 user_part_tables,user_tab_partitions 兩個資料字典(索引分割槽、組織分割槽等資訊也有對應的資料字典,後續示例會逐步提及)。 user_part_tables:記錄分割槽的表的資訊; user_tab_partitions:記錄表的分割槽的資訊。

例如:

JSSWEB> select table_name,partitioning_type,partition_count

2              From user_part_tables where table_name='T_PARTITION_RANGE';

TABLE_NAME                                     PARTITI PARTITION_COUNT

------------------------------ ------- ---------------

T_PARTITION_RANGE                         RANGE                              4

JSSWEB> select partition_name,high_value,tablespace_name

2      from user_tab_partitions where table_name='T_PARTITION_RANGE' 3order by partition_position;

PARTITION_NAME                              HIGH_VALUE TABLESPACE_NAME

------------------------------ ---------- --------------------

T_RANGE_P1                                     10                TBSPART01

T_RANGE_P2                                     20                TBSPART02

T_RANGE_P3                                     30                TBSPART03

T_RANGE_PMAX                                  MAXVALUE     TBSPART04

   建立 global 索引 range 分割槽:

JSSWEB> create index idx_parti_range_id on t_partition_range(id)

2              global partition by range(id)(

3              partition i_range_p1 values less than (10) tablespace tbspart01,

4              partition i_range_p2 values less than (40) tablespace tbspart02,

5              partition i_range_pmax values less than (maxvalue) tablespace tbspart03);

索引已建立。

由上例可以看出,建立 global 索引的分割槽與建立表的分割槽語句格式完全相同,而且其分割槽形式與索引

所在表的分割槽形式沒有關聯關係。

注意:我們這裡藉助上面的表 t_partition_range 來演示建立 range 分割槽的 global 索引,並不表示 range

分割槽的表,只能建立 range 分割槽的 global 索引,只要你想,也可以為其建立 hash 分割槽的 global 索引。

查詢索引的分割槽資訊可以透過 user_part_indexesuser_ind_partitions 兩個資料字典:

JSSWEB> select index_name, partitioning_type, partition_count

2              From user_part_indexes

3              where index_name = 'IDX_PARTI_RANGE_ID';

INDEX_NAME                                     PARTITI PARTITION_COUNT

------------------------------ ------- ---------------

IDX_PARTI_RANGE_ID                       RANGE                              3

JSSWEB> select partition_name, high_value, tablespace_name

2              from user_ind_partitions

3              where index_name = 'IDX_PARTI_RANGE_ID'

4              order by partition_position;

PARTITION_NAME                              HIGH_VALUE TABLESPACE_NAME

------------------------------ ---------- --------------------

I_RANGE_P1                                     10                TBSPART01

I_RANGE_P2                                     40                TBSPART02

I_RANGE_PMAX                                  MAXVALUE     TBSPART03

   Local 分割槽索引的建立最簡單,例如:仍然藉助 t_partition_range 表來建立索引

--首先刪除之前建立的 global 索引

JSSWEB> drop index IDX_PARTI_RANGE_ID;

索引已刪除。

JSSWEB> create index IDX_PARTI_RANGE_ID on T_PARTITION_RANGE(id) local;

索引已建立。

查詢相關資料字典:

JSSWEB> select index_name, partitioning_type, partition_count

2              From user_part_indexes

3              where index_name = 'IDX_PARTI_RANGE_ID';

INDEX_NAME                                     PARTITI PARTITION_COUNT

------------------------------ ------- ---------------

IDX_PARTI_RANGE_ID                       RANGE                              4

JSSWEB> select partition_name, high_value, tablespace_name

2              from user_ind_partitions

3              where index_name = 'IDX_PARTI_RANGE_ID'

4              order by partition_position;

PARTITION_NAME                              HIGH_VALUE TABLESPACE_NAME

------------------------------ ---------- --------------------

T_RANGE_P1                                     10                TBSPART01

T_RANGE_P2                                     20                TBSPART02

T_RANGE_P3       30    TBSPART03 T_RANGE_PMAX  MAXVALUE  TBSPART04

可以看出,local 索引的分割槽完全繼承表的分割槽的屬性,包括分割槽型別,分割槽的範圍值即不需指定也不

能更改,這就是前面說的:local 索引的分割槽維護完全依賴於其索引所在表。

不過呢分割槽名稱,以及分割槽所在表空間等資訊是可以自定義的,例如:

SQL> create index IDX_PART_RANGE_ID ON T_PARTITION_RANGE(id) local (

2       partition i_range_p1 tablespace tbspart01,

3       partition i_range_p2 tablespace tbspart01,

4       partition i_range_p3 tablespace tbspart02,

5       partition i_range_pmax tablespace tbspart02 6    );

索引已建立。

SQL> select index_name, partitioning_type, partition_count

2           From user_part_indexes

3           where index_name = 'IDX_PART_RANGE_ID';

INDEX_NAME                                 PARTITI PARTITION_COUNT

------------------------------ ------- ---------------

IDX_PART_RANGE_ID                     RANGE                              4

SQL> select partition_name, high_value, tablespace_name

2           from user_ind_partitions

3           where index_name = 'IDX_PART_RANGE_ID'

4           order by partition_position;

PARTITION_NAME    HIGH_VALUE          TABLESPACE_NAME

--------------- --------------- --------------------

I_RANGE_P1           10                         TBSPART01

I_RANGE_P2           20                         TBSPART01

I_RANGE_P3           30                         TBSPART02

I_RANGE_PMAX       MAXVALUE              TBSPART02

2、建立 hash 分割槽

語法如下:[:hash_partitioning.gif]

clip_image003

語法看起來比 range 複雜,其實使用起來比 range 更簡單,這裡需要我們指定的有:

l  column:分割槽依賴列(支援多個,中間以逗號分隔);

l  partition:指定分割槽,有兩種方式:

n 直接指定分割槽名,分割槽所在表空間等資訊 n 只指定分割槽數量,和可供使用的表空間。

建立 hash 分割槽表

JSSWEB> create table t_partition_hash (id number,name varchar2(50))

2       partition by hash(id)(

3       partition t_hash_p1 tablespace tbspart01,

4       partition t_hash_p2 tablespace tbspart02,

5       partition t_hash_p3 tablespace tbspart03);

表已建立。

要實現同樣效果,你還可以這樣:

JSSWEB> create table t_partition_hash2 (id number,name varchar2(50))

2       partition by hash(id)

3       partitions 3 store in(tbspart01,tbspart02,tbspart03);

表已建立。

這就是上面說的,直接指定分割槽數量和可供使用的表空間。

提示:這裡分割槽數量和可供使用的表空間數量之間沒有直接對應關係。分割槽數並不一定要等於表空間數。

要查詢表的分割槽資訊,仍然是透過 user_part_tables,user_tab_partitions 兩個資料字典,這裡不再舉例。

Global 索引 hash 分割槽

Hash 分割槽索引的子句與 hash 分割槽表的建立子句完全相同,例如:

JSSWEB> create index idx_part_hash_id on t_partition_hash(id)

2       global partition by hash(id)

3       partitions 3 store in(tbspart01,tbspart02,tbspart03);

索引已建立。

 
  clip_image005


查詢索引的分割槽資訊也仍是透過 user_part_indexesuser_ind_partitions 兩個資料字典,不再舉例。

建立 Local 索引

在前面學習 range 分割槽時,我們已經對 Local 索引的特性做了非常清晰的概述,因此這裡也不再舉例,如有疑問,建議再仔細複習 range 分割槽的相關示例,如果還有疑問,當面問我好了:)

綜上:

?對於 global 索引分割槽而言,在 10g 中只能支援 range 分割槽和 hash 分割槽,因此後續示例中不會再提及。

?對於 local 索引分割槽而言,其分割槽形式完全依賴於索引所在表的分割槽形式,不管從建立語法還是理解難度均無技術含量,因此後續也不再提供示例。

?注意,在建立索引時如果不顯式指定 global local,則預設是 global

?注意,在建立 global 索引時如果不顯式指定分割槽子句,則預設不分割槽(廢話)

3、建立 list 分割槽

建立語法如下:[圖:list_partitioning.gif]

需要我們指定的有:

l   column:分割槽依賴列,注意:只能是一個;

l   partition:分割槽名稱;

l   literal:分割槽對應值,注意:每個分割槽可以對應多個值;

l   tablespace_clause:分割槽的儲存屬性,例如所在表空間等屬性(可為空),預設繼承基表所在表空間的屬性。

建立 list 分割槽表示例:

JSSWEB> create table t_partition_list (id number,name varchar2(50))

2       partition by list(id)(

3       partition t_list_p1 values (1,2,3,4,5,6,7,8,9) tablespace tbspart01,

4       partition t_list_p2 values (10,11,12,13,14,15,16,17,18,19) tablespace tbspart02,

5       partition t_list_p3 values (20,21,22,23,24,25,26,27,28,29) tablespace tbspart03, 6 partition t_list_pd values (default) tablespace tbspart04);

表已建立。

上例能夠實現與前面 range 分割槽示例相同的效果,當然針對本示例而言,list 分割槽顯然不好用啊~~~

4、建立 range-hash 組合分割槽

語法如下:圖[composite_partitioning.gif]

clip_image006

需要我們指定的有:

l  column_list:分割槽依賴列(支援多個,中間以逗號分隔);

l  subpartition:子分割槽方式,有兩處:

n  Subpartition_by_list:語法與 list 分割槽完全相同,只不過把關鍵字 partition 換成 subpartition

n  Subpartition_by_hash:語法與 hash 分割槽完全相同,只不過把關鍵字 partition 換成 subpartition

l   partition:分割槽名稱;

l   range_partition_values_clause:range 分割槽範圍值的語法;

l   tablespace_clause:分割槽的儲存屬性,例如所在表空間等屬性(可為空),預設繼承基表所在表空間的屬性。

組合分割槽相對於普通分割槽,語法上稍稍複雜了一些,但也正因如此,其子分割槽的建立可以非常靈活,

下面分別舉幾個例子(注:僅示例,並非窮舉所有形式)

   為所有分割槽各建立 4 hash 子分割槽

 

JSSWEB> create table t_partition_rh (id number,name varchar2(50))

2       partition by range(id) subpartition by hash(name)

3       subpartitions 4 store in (tbspart01, tbspart02, tbspart03,tbspart04)(

4       partition t_r_p1 values less than (10) tablespace tbspart01,

5       partition t_r_p2 values less than (20) tablespace tbspart02,

6       partition t_r_p3 values less than (30) tablespace tbspart03,

7       partition t_r_pd values less than (maxvalue) tablespace tbspart04);

表已建立。

JSSWEB> select partitioning_type,subpartitioning_type,partition_count,def_subpartition_count

              2   From user_part_tables where table_name='T_PARTITION_RH';

PARTITI SUBPART PARTITION_COUNT DEF_SUBPARTITION_COUNT

------- ------- --------------- ----------------------

         RANGE     HASH                                4                                       4

JSSWEB> select partition_name,subpartition_count,high_value

              2   from user_tab_partitions where table_name='T_PARTITION_RH';

         PARTITION_NAME    SUBPARTITION_COUNT HIGH_VALUE

--------------- ------------------ ----------

          T_R_P2                                               4 20

          T_R_P3                                               4 30

         T_R_PD                                               4 MAXVALUE

          T_R_P1                                               4 10

JSSWEB> select partition_name,subpartition_name,tablespace_name

              2   from user_tab_subpartitions where table_name='T_PARTITION_RH';

         PARTITION_NAME    SUBPARTITION_NAME                        TABLESPACE_NAME

--------------- ------------------------------ --------------------

          T_R_P2                 SYS_SUBP140                                   TBSPART02

          T_R_P2                 SYS_SUBP139                                   TBSPART02

          T_R_P2                 SYS_SUBP138                                   TBSPART02

          T_R_P2                 SYS_SUBP137                                   TBSPART02

          T_R_P3                 SYS_SUBP144                                   TBSPART03

          T_R_P3                 SYS_SUBP143                                   TBSPART03

          T_R_P3                 SYS_SUBP142                                   TBSPART03

          T_R_P3                 SYS_SUBP141                                   TBSPART03

         T_R_PD                  SYS_SUBP148                                   TBSPART04

         T_R_PD                  SYS_SUBP147                                   TBSPART04

         T_R_PD                  SYS_SUBP146                                   TBSPART04

         T_R_PD                  SYS_SUBP145                                   TBSPART04

T_R_P1

SYS_SUBP133

TBSPART01

T_R_P1

SYS_SUBP136

TBSPART01

T_R_P1

SYS_SUBP135

TBSPART01

T_R_P1

已選擇 16 行。

SYS_SUBP134

TBSPART01

這裡我們要學到一個新的資料字典:user_tab_subpartitions,用於查詢表的子分割槽資訊。

   對某個分割槽建立 hash 子分割槽

JSSWEB> create table t_partition_rh (id number,name varchar2(50))

2           partition by range(id) subpartition by hash(name)(

3           partition t_r_p1 values less than (10) tablespace tbspart01,

4           partition t_r_p2 values less than (20) tablespace tbspart02,

5           partition t_r_p3 values less than (30) tablespace tbspart03

6           (subpartition t_r_p3_h1 tablespace tbspart01,

7           subpartition t_r_p3_h2 tablespace tbspart02,

8           subpartition t_r_p3_h3 tablespace tbspart03),

9           partition t_r_pd values less than (maxvalue) tablespace tbspart04);

表已建立。

JSSWEB> select partitioning_type,subpartitioning_type,partition_count,def_subpartition_count

2       From user_part_tables where table_name='T_PARTITION_RH';

PARTITI SUBPART PARTITION_COUNT DEF_SUBPARTITION_COUNT

------- ------- --------------- ----------------------

RANGE      HASH                                4                                       1

JSSWEB> select partition_name,subpartition_count,high_value

2       from user_tab_partitions where table_name='T_PARTITION_RH';

PARTITION_NAME    SUBPARTITION_COUNT HIGH_VALUE

--------------- ------------------ ----------

T_R_P1                                               1 10

T_R_P2                                               1 20

T_R_P3                                               3 30

T_R_PD                                                1 MAXVALUE

JSSWEB> select partition_name,subpartition_name,tablespace_name

2       from user_tab_subpartitions where table_name='T_PARTITION_RH';

PARTITION_NAME    SUBPARTITION_NAME                         TABLESPACE_NAME

--------------- ------------------------------ --------------------


T_R_P1

SYS_SUBP149

TBSPART01

T_R_P2

SYS_SUBP150

TBSPART02

T_R_P3

T_R_P3_H3

TBSPART03

T_R_P3

T_R_P3_H2

TBSPART02

T_R_P3

T_R_P3_H1

TBSPART01

T_R_PD

已選擇 6 行。

SYS_SUBP151

TBSPART04

當然,還可以給各個分割槽指定不同的子分割槽

JSSWEB> create table t_partition_rh (id number,name varchar2(50))

2              partition by range(id) subpartition by hash(name)(

3              partition t_r_p1 values less than (10) tablespace tbspart01,

4              partition t_r_p2 values less than (20) tablespace tbspart02

5              (subpartition t_r_p2_h1 tablespace tbspart01,

6              subpartition t_r_p2_h2 tablespace tbspart02),

7              partition t_r_p3 values less than (30) tablespace tbspart03

8              subpartitions 3 store in (tbspart01,tbspart02,tbspart03),

9              partition t_r_pd values less than (maxvalue) tablespace tbspart04

10          (subpartition t_r_p3_h1 tablespace tbspart01,

11          subpartition t_r_p3_h2 tablespace tbspart02,

12          subpartition t_r_p3_h3 tablespace tbspart03) 13       );

表已建立。

JSSWEB> select partitioning_type,subpartitioning_type,partition_count,def_subpartition_count

2     From user_part_tables where table_name='T_PARTITION_RH';

PARTITI SUBPART PARTITION_COUNT DEF_SUBPARTITION_COUNT

------- ------- --------------- ----------------------

RANGE    HASH                                4                                       1

JSSWEB> select partition_name,subpartition_count,high_value

2     from user_tab_partitions where table_name='T_PARTITION_RH';

PARTITION_NAME  SUBPARTITION_COUNT HIGH_VALUE

--------------- ------------------ ----------

T_R_P1                                              1 10

          T_R_P2                                               2 20

          T_R_P3                                               3 30

         T_R_PD                                               3 MAXVALUE

JSSWEB> select partition_name,subpartition_name,tablespace_name

2       from user_tab_subpartitions where table_name='T_PARTITION_RH';

PARTITION_NAME    SUBPARTITION_NAME                        TABLESPACE_NAME

--------------- ------------------------------ --------------------

T_R_P1                  SYS_SUBP152                                   TBSPART01

T_R_P2                  T_R_P2_H2                                      TBSPART02

T_R_P2                  T_R_P2_H1                                      TBSPART01

T_R_P3                  SYS_SUBP155                                   TBSPART03

T_R_P3                  SYS_SUBP154                                   TBSPART02

T_R_P3                  SYS_SUBP153                                   TBSPART01

T_R_PD                  T_R_P3_H3                                      TBSPART03

T_R_PD                  T_R_P3_H2                                      TBSPART02

T_R_PD                  T_R_P3_H1                                      TBSPART01

已選擇 9 行。

提示:由上兩例可以看出,未顯式指定子分割槽的分割槽,系統會自動建立一個子分割槽。

分割槽模板的應用

oracle 還提供了一種稱為分割槽模板的功能,在指定子分割槽信賴列之後,制訂子分割槽的儲存模板,各個

分割槽即會按照子分割槽模式建立子分割槽,例如:

JSSWEB> create table t_partition_rh (id number,name varchar2(50))

2           partition by range(id) subpartition by hash(name)

3           subpartition template (

4           subpartition h1 tablespace tbspart01,

5           subpartition h2 tablespace tbspart02,

6           subpartition h3 tablespace tbspart03,

7           subpartition h4 tablespace tbspart04)(

8           partition t_r_p1 values less than (10) tablespace tbspart01,

9           partition t_r_p2 values less than (20) tablespace tbspart02,

10       partition t_r_p3 values less than (30) tablespace tbspart03,

11       partition t_r_pd values less than (maxvalue) tablespace tbspart04);

表已建立。

JSSWEB> select partition_name,subpartition_name,tablespace_name

2   from user_tab_subpartitions where table_name='T_PARTITION_RH';

PARTITION_NAMESUBPARTITION_NAME                        TABLESPACE_NAME

 

--------------- ------------------------------ --------------------

 

 

 

T_R_P1                  T_R_P1_H4

TBSPART01

 

 

T_R_P1                  T_R_P1_H3

TBSPART01

 

 

T_R_P1                  T_R_P1_H2

TBSPART01

 

 

T_R_P1                  T_R_P1_H1

TBSPART01

 

T_R_P2

T_R_P2_H4

TBSPART02

T_R_P2

T_R_P2_H3

TBSPART02

T_R_P2

T_R_P2_H2

TBSPART02

T_R_P2

T_R_P2_H1

TBSPART02

T_R_P3

T_R_P3_H4

TBSPART03

T_R_P3

T_R_P3_H3

TBSPART03

T_R_P3

T_R_P3_H2

TBSPART03

T_R_P3

T_R_P3_H1

TBSPART03

T_R_PD

T_R_PD_H4

TBSPART04

T_R_PD

T_R_PD_H3

TBSPART04

T_R_PD

T_R_PD_H2

TBSPART04

T_R_PD

已選擇 16 行。

T_R_PD_H1

TBSPART04

         

5、建立 range-list 組合分割槽

Range-list 組合分割槽的建立與 range-hash 極為相似,只是子分割槽為 list 分割槽,當然同樣也可以應用分割槽

模板,下面也舉一個示例:

JSSWEB> create table t_partition_rl (id number,name varchar2(50))

2           partition by range(id) subpartition by list(name)

3           subpartition template (

4           subpartition l1 values ('aa') tablespace tbspart01,

5           subpartition l2 values ('bb') tablespace tbspart02,

6           subpartition l3 values ('cc') tablespace tbspart03,

7           subpartition l4 values ('dd') tablespace tbspart04)(

8           partition t_r_p1 values less than (10) tablespace tbspart01,

9           partition t_r_p2 values less than (20) tablespace tbspart02,

10       partition t_r_p3 values less than (30) tablespace tbspart03,

11       partition t_r_pd values less than (maxvalue) tablespace tbspart04);

表已建立。

JSSWEB> select partition_name,subpartition_name,tablespace_name

2   from user_tab_subpartitions where table_name='T_PARTITION_RL';

PARTITION_NAMESUBPARTITION_NAME                        TABLESPACE_NAME

--------------- ------------------------------ --------------------

T_R_P1

T_R_P1_L4

TBSPART01

T_R_P1

T_R_P1_L3

TBSPART01

T_R_P1

T_R_P1_L2

TBSPART01

T_R_P1

T_R_P1_L1

TBSPART01

T_R_P2

T_R_P2_L4

TBSPART02


T_R_P2

T_R_P2_L3

TBSPART02

T_R_P2

T_R_P2_L2

TBSPART02

T_R_P2

T_R_P2_L1

TBSPART02

T_R_P3

T_R_P3_L4

TBSPART03

T_R_P3

T_R_P3_L3

TBSPART03

T_R_P3

T_R_P3_L2

TBSPART03

T_R_P3

T_R_P3_L1

TBSPART03

T_R_PD

T_R_PD_L4

TBSPART04

T_R_PD

T_R_PD_L3

TBSPART04

T_R_PD

T_R_PD_L2

TBSPART04

T_R_PD

已選擇 16 行。

T_R_PD_L1

TBSPART04

其它方式的建立對於 range-list 同樣好使,這裡不再舉例,如有不明,請自學複習前章 range_hash 組合

分割槽。

對於複合分割槽的 local 索引,我們也舉一個示例,檢視其分割槽情況:

SQL> create index idx_part_rl_id on t_partition_rl(id) local;

索引已建立。

又可以學幾個資料字典:user_part_indexesuser_ind_partitions 前面已經認識了,user_ind_subpartitions 用來查詢索引的子分割槽資訊。

SQL> select table_name,partitioning_type,

2                                partition_count,def_subpartition_count

3                                from user_part_indexes

4                                where index_name = 'IDX_PART_RL_ID';

TABLE_NAME                                     PARTITI PARTITION_COUNT DEF_SUBPARTITION_COUNT

------------------------------ ------- --------------- ----------------------

T_PARTITION_RL                              RANGE                              4                                       4

SQL> select partition_name, subpartition_count, high_value

2              from user_ind_partitions

3              where index_name = 'IDX_PART_RL_ID';

PARTITION_NAME    SUBPARTITION_COUNT HIGH_VALUE

--------------- ------------------ ---------------

T_R_P1                                                4 10

T_R_P2                                                4 20

T_R_P3                                                4 30

T_R_PD                                                4 MAXVALUE

SQL> select partition_name, subpartition_name, high_value, tablespace_name

2              from user_ind_subpartitions

3              where index_name = 'IDX_PART_RL_ID';

         PARTITION_NAME    SUBPARTITION_NAME                        HIGH_VALUE

TABLESPACE_NAME

--------------- ------------------------------ --------------- --------------------

          T_R_P1                 T_R_P1_L1                                       'aa'                     TBSPART01

T_R_P1  T_R_P1_L2    'bb'  TBSPART01 T_R_P1    T_R_P1_L3    'cc'   TBSPART01

T_R_P1  T_R_P1_L4    'dd'  TBSPART01 T_R_P2    T_R_P2_L1    'aa'   TBSPART02

T_R_P2  T_R_P2_L2    'bb'  TBSPART02 T_R_P2    T_R_P2_L3    'cc'   TBSPART02

T_R_P2  T_R_P2_L4    'dd'  TBSPART02 T_R_P3    T_R_P3_L1    'aa'   TBSPART03

T_R_P3  T_R_P3_L2    'bb'  TBSPART03 T_R_P3    T_R_P3_L3    'cc'   TBSPART03

          T_R_P3                 T_R_P3_L4                                       'dd'                     TBSPART03

         T_R_PD                  T_R_PD_L1                                       'aa'                     TBSPART04

T_R_PD  T_R_PD_L2   'bb'  TBSPART04 T_R_PD   T_R_PD_L3   'cc'   TBSPART04

         T_R_PD                  T_R_PD_L4                                       'dd'                     TBSPART04

已選擇 16 行。

還是與表的分割槽格式一樣,不管是普通分割槽還是複合分割槽,local 索引都沒啥自主權啊。

6、公共準則

1、         如果選擇的分割槽不能確保各分割槽內記錄量的基本平均,則這種分割槽方式有可能是不恰當的。

比如對於 range 分割槽,假設分了 10 個分割槽,而其中一個分割槽中的記錄數佔總記錄數的 90%,其它 9 個分割槽只佔總記錄數的 10%,則這個分割槽方式就起不到資料平衡的作用。當然,如果你的目的並不是為了平衡,只是為了區分資料,ok,對於這種情況,我想說的是,你務必要意識到存在這個問題。

2、         對於分割槽的表或索引,其所涉及的所有分割槽,其塊大小必須一致。

最後,建議對於上面建立的表或建表指令碼妥善儲存並記憶,後面我們需要頻繁用到,後續示例將均主要依賴前文中建立的表進行:)

二、如何管理

對於分割槽的表的操作很多,其中某些操作僅針對某些分割槽有效,為了避免在演示過程中浪費過多口水標註哪些操作適用於哪些分割槽,我們們先在這兒列個表,哪個操作適用於哪種分割槽格式具體可以先參考下面這個表格:

分割槽表

Range

List

Hash

Range-Hash

Range-List

是否帶來IO操作

增加分割槽

(add partition)

支援

支援

支援

支援

支援

hash型別外,均不變帶來大量IO

收縮分割槽

(coalesce partitions)

/

/

支援

分割槽:/

子分割槽:支援

/

刪除分割槽

(drop partition)

支援

支援

/

分割槽:支援子分割槽:/

支援

交換分割槽

(exchange partition)

支援

支援

支援

支援

支援

合併分割槽

(merge partition)

支援

支援

/

分割槽:支援子分割槽:/

支援

修改預設屬性

(modify default attributes)

支援

支援

支援

支援

支援

修改分割槽當前屬性

(modify partition)

支援

支援

支援

支援

支援

List分割槽增加值

(modify partition add values)

/

支援

/

/

分割槽:/

子分割槽:支援

List分割槽刪除值

(modify partition drop values)

/

支援

/

/

分割槽:/

子分割槽:支援

單純刪除操作無,但可能為了實現成功刪除,之前的準備操作會帶來一定量的IO

修改子分割槽模板

(set subpartition template)

/

/

/

支援

支援

移動分割槽

(move partition)

支援

支援

支援

分割槽:支援子分割槽:/

分割槽:支援子分割槽:/

重新命名分割槽

(rename partition)

支援

支援

支援

支援

支援

拆分分割槽

(split partition)

支援

支援

/

分割槽:支援子分割槽:/

支援

截斷分割槽

(truncate partition)

支援

支援

支援

支援

支援

注:上述 IO 列的評估建立在假設分割槽中均存在一定量資料,並忽略修改資料字典可能觸發的 IO,忽略造成的索引的重編譯帶來的 IO

分割槽索引的操作也有一張表黑黑,如下:

分割槽索引

索引型別

Range

List

Hash

組合分割槽

是否帶來IO操作

增加分割槽

(add partition)

全域性

/

/

支援

/

本地

/

/

/

/

 

刪除分割槽

(drop partition)

全域性

支援

/

/

/

本地

/

/

/

/

 

修改預設屬性

(modify default attributes)

全域性

支援

/

/

/

本地

支援

支援

支援

支援

修改分割槽當前屬性

全域性

支援

/

/

/

(modify partition)

本地

支援

支援

支援

支援

重編譯分割槽

(rebuild partition)

全域性

支援

/

/

/

本地

支援

支援

支援

支援

重新命名分割槽

(rename partition)

全域性

支援

/

/

/

本地

支援

支援

支援

支援

拆分分割槽

(split partition)

全域性

支援

/

/

/

本地

/

/

/

/

 

另外 local 索引前頭我們多次提到了,其維護會在 oracle 操作表分割槽的時候自動進行,需要注意的是 global

索引,當 global 索引所在表執行 alter table 涉及下列操作時,會導至該索引失效:

?  ADD PARTITION | SUBPARTITION

?  COALESCE PARTITION | SUBPARTITION

?  DROP PARTITION | SUBPARTITION

?  EXCHANGE PARTITION | SUBPARTITION

?  MERGE PARTITION | SUBPARTITION

?  MOVE PARTITION | SUBPARTITION

?  SPLIT PARTITION | SUBPARTITION

?  TRUNCATE PARTITION | SUBPARTITION

因此,建議使用者在執行上述操作 sql 語句後附加 update indexes 子句,oracle 即會自動維護全域性索引,當然,需要注意這中間有一個平衡,你要平衡操作 ddl 的時間和重建索引哪個時間更少,以決定是否需要附加 update indexes 子句。

分割槽表的管理

1、增加表分割槽(add partition) 增加表分割槽適應於所有的分割槽形式,其語法是 alter table tbname add partition .....

但是,需要注意對於像 list,range 這種存在範圍值的分割槽,所要增加的分割槽值必須要大於當前分割槽中的最大值(如果當前存在 maxvalue default 的分割槽,add partition 會報錯,這種情況只能使用 split,後面會講到),hash 分割槽則無此限制。

例如:

JSSWEB> create table t_partition_range (id number,name varchar2(50))

2           partition by range(id)(

3           partition t_range_p1 values less than (10) tablespace tbspart01,

4           partition t_range_p2 values less than (20) tablespace tbspart02,

5           partition t_range_p3 values less than (30) tablespace tbspart03

6           );

表已建立。

JSSWEB> alter table t_partition_range

2   add partition t_range_p4 values less than(40);

表已更改。

Hash list 的語法與上類似,這裡不再舉例。

注意:

1、    對於 hash 分割槽,當你執行 add partition 操作的時候,oracle 會自動選擇一個分割槽,並重新分配部分記錄到新建的分割槽,這也意味著有可能帶來一些 IO 操作。

2、    執行 alter table 時未指定 update indexes 子句:如果是 range/list 分割槽,其 local 索引和 global 索引不會受影響;

如果是 hash 分割槽,新加分割槽及有資料移動的分割槽的 local 索引和 glocal 索引會被置為 unuseable,需要重新編譯。

3、    複合分割槽完全適用上述所述規則。

2、收縮表分割槽(coalesce partitions)

Coalesce partition 是個很有意思的分割槽功能,僅能被應用於 hash 分割槽或複合分割槽的 hash 子分割槽,執行之後,會自動收縮當前的表分割槽,比如某表當前有 5 hash 分割槽,執行 alter table tbname coalesce partitions 後就變成 4 個,再執行一次就變成 3 個,再執行一次就變 2 個,再執行一次就...........就報錯了:),對於已分割槽的表至少要有一個分割槽存在的嘛!

例如:

JSSWEB> select table_name,partition_name from user_tab_partitions

2         where table_name='T_PARTITION_HASH';

TABLE_NAME                                     PARTITION_NAME

------------------------------ ------------------------------

T_PARTITION_HASH                          T_HASH_P2

T_PARTITION_HASH                          T_HASH_P3

T_PARTITION_HASH                          T_HASH_P4

T_PARTITION_HASH                          T_HASH_P5

T_PARTITION_HASH                          T_HASH_P1

JSSWEB> alter table t_partition_hash coalesce partition;

表已更改。

JSSWEB> select table_name,partition_name from user_tab_partitions

2         where table_name='T_PARTITION_HASH';

TABLE_NAME                                     PARTITION_NAME

------------------------------ ------------------------------

T_PARTITION_HASH                          T_HASH_P2

T_PARTITION_HASH                          T_HASH_P3

T_PARTITION_HASH                          T_HASH_P4

T_PARTITION_HASH  T_HASH_P1 注意,收縮的只是分割槽,並不會影響到資料,但是視被收縮分割槽中資料的多少,收縮表分割槽也會涉及

IO 操作。

另外如果你在執行該語句時沒有指定 update indexes 子句,收縮過程中有資料改動的分割槽其 local 索引

glocal 索引都會失效,需要重新編譯。

3、刪除表分割槽(drop partition)

刪除表分割槽包含兩種操作,分別是:

?  刪除分割槽:alter table [tbname] drop partition [ptname];

?  刪除子分割槽:alter table [tbname] drop subpartition [ptname];

hash 分割槽和 hash 子分割槽外,其它的分割槽格式都可以支援這項操作。

例如,刪除分割槽:

JSSWEB> select table_name,partition_name

2       from user_tab_partitions where table_name='T_PARTITION_LIST';

TABLE_NAME                                     PARTITION_NAME

------------------------------ ------------------------------

T_PARTITION_LIST                          T_LIST_P1

T_PARTITION_LIST                          T_LIST_P2

T_PARTITION_LIST                          T_LIST_P3

T_PARTITION_LIST                          T_LIST_PD

JSSWEB> alter table t_partition_list drop partition t_list_p2;

表已更改。

提示,drop partition 時,該分割槽記憶體儲的資料也將同時刪除,例如:

JSSWEB> insert into t_partition_list values (1,'a');

..........

--插入一批記錄,分佈於當前各個分割槽

..........

JSSWEB> commit;

提交完成。

JSSWEB> select *from t_partition_list;

ID NAME

---------- --------------------------------------------------

1  a

2  b

21  a

22  b

--單獨查詢 t_list_p3 分割槽,當前有資料

JSSWEB> select *from t_partition_list partition(t_list_p3);

ID NAME

---------- --------------------------------------------------

21  a

22  b

--刪除 t_list_p3 分割槽,資料會被同時刪除

JSSWEB> alter table t_partition_list drop partition t_list_p3;

表已更改。

JSSWEB> select *from t_partition_list partition(t_list_p3);

select *from t_partition_list partition(t_list_p3)

*

1 行出現錯誤:

ORA-02149: 指定的分割槽不存在

JSSWEB> select *from t_partition_list;

ID NAME

---------- --------------------------------------------------

1  a

2  b

由於是 ddl 操作,這種刪除也會是非常迅速的,因此如果你確認某個分割槽的資料都要被刪除,使用 drop partition 會比 delete 更加高效。如果你的本意是希望刪除掉指定的分割槽但保留資料,你應該使用 merge partition,後面也會講到。

同樣,如果你在執行該語句時沒有指定 update indexes 子句,也會導致 glocal 索引的失效,至於 local 索引嘛,刪除分割槽時對應的索引分割槽會被同時刪除,但其它分割槽的 local 索引不會受到影響。

4、交換表分割槽(Exchange Partitions)

直白的說就是遷移資料。遷移資料的方式很多,為什麼要使用 exchange partition 的方式呢,表急,聽三思慢慢道來。

Exchange partition 提供了一種方式,讓你在表與表或分割槽與分割槽之間遷移資料,注意不是將錶轉換成分割槽或非分割槽的形式,而僅只是遷移表中資料(互相遷移),由於其號稱是採用了更改資料字典的方式,因此效率最高(幾乎不涉及 io 操作)Exchange partition 適用於所有分割槽格式,你可以將資料從分割槽表遷移到非分割槽表,也可以從非分割槽表遷移至分割槽表,或者從 hash partition range partition 諸如此類吧。

其語法很簡單:alter table tbname1 exchange partition/subpartition ptname with table tbname2;

Exchange partition 遷移的方式也很有意思,言語表達怕大家聽不明白,下面直接透過示例來表達:借用前文中建立的空分割槽表:t_partition_range,並插入幾條記錄

JSSWEB> create table t_partition_range (id number,name varchar2(50))

2    partition by range(id)(

3    partition t_range_p1 values less than (10) tablespace tbspart01,

4    partition t_range_p2 values less than (20) tablespace tbspart02, 5partition t_range_p3 values less than (30) tablespace tbspart03,

6           partition t_range_pmax values less than (maxvalue) tablespace tbspart04

7           );

表已建立。

JSSWEB> insert into t_partition_range values (11,'a');

已建立 1 行。

JSSWEB> insert into t_partition_range values (12,'b');

已建立 1 行。

JSSWEB> insert into t_partition_range values (13,'c');

已建立 1 行。

JSSWEB> commit;

提交完成。

再建立一個非分割槽表,結構與 t_partition_range 相同

JSSWEB> create table t_partition_range_tmp (id number,name varchar2(50));

表已建立。

執行交換分割槽(我們知道剛插入到 range 分割槽表的資料都在分割槽 t_range_p2 中,因此這裡指定交換該分割槽)

JSSWEB> alter table t_partition_range exchange partition t_range_p2 2 with table t_partition_range_tmp;

表已更改。

看看效果如何:

JSSWEB> select * from t_partition_range partition(t_range_p2);

未選定行

JSSWEB> select * from t_partition_range_tmp;

ID NAME

---------- --------------------------------------------------

11  a

12  b

13  c

記錄成功交換到未分割槽的表中。

我們再執行一次 exchange partition 的命令,看看又會發生什麼呢

JSSWEB> select *from t_partition_range partition(t_range_p2);

ID NAME

---------- --------------------------------------------------

11  a

12  b

13  c

JSSWEB> select *from t_partition_range_tmp;

未選定行

又交換回來了,有點兒意思。

再做個更加明確的測試,我們往未分割槽的表中加入一些記錄後再執行 exchange partition,看看會發生什

麼呢:

JSSWEB> insert into t_partition_range_tmp values (15,'d');

已建立 1 行。

JSSWEB> insert into t_partition_range_tmp values (16,'e');

已建立 1 行。

JSSWEB> insert into t_partition_range_tmp values (17,'d');

已建立 1 行。

JSSWEB> alter table t_partition_range exchange partition t_range_p2 2 with table t_partition_range_tmp;

表已更改。

JSSWEB> select *from t_partition_range partition(t_range_p2);

ID NAME

---------- --------------------------------------------------

15  d

16  e

17  d

JSSWEB> select *from t_partition_range_tmp;

ID NAME

---------- --------------------------------------------------

11  a

12  b

13  c

這就是前面所說的,互相交換的意思~~

注意:

l  涉及交換的兩表之間表結構必須一致,除非附加 with validation 子句;

l  如果是從非分割槽表向分割槽表做交換,非分割槽表中的資料必須符合分割槽表中指定分割槽的規則,除非附加 without validation 子句;

l  如果從分割槽表向分割槽表做交換,被交換的分割槽的資料必須符合分割槽規則,除非附加 without validation 子句;

l  Global 索引或涉及到資料改動了的 global 索引分割槽會被置為 unusable,除非附加 update indexes 子句。

提示:

一旦附加了 without validation 子句,則表示不再驗證資料有效性,因此指定該子句時務必慎重。

例如:

JSSWEB> insert into t_partition_range_tmp values (8,'g');

已建立 1 行。

JSSWEB> alter table t_partition_range exchange partition t_range_p2 2 with table t_partition_range_tmp without validation;

表已更改。

JSSWEB> select *from t_partition_range partition(t_range_p2);

ID NAME

---------- --------------------------------------------------

11  a

12  b

13  c

8 g

雖然新插入的記錄並不符合 t_range_p2 分割槽的範圍值,但指定了 without validation 後,資料仍然轉換


成功。

5、合併表分割槽(Merge Partitions)

合併兩個分割槽成一個,適用於除 hash 之外的其它所有分割槽形式(hash 分割槽有 coalesce partition 的嘛,前頭剛剛講過)

語法很簡單:alter table tbname merge partitions/subpartitions pt1,pt2 into partition/subpartition pt3; 同樣也支援 update indexes 子句以避免單獨執行造成索引失效的問題。

需要注意一點,要合併的兩個分割槽必須是連續的,這點是由分割槽本身的特性所決定的,如例:

JSSWEB> alter table t_partition_range merge partitions t_range_p1,t_range_p2 2 into partition t_range_pnew;

表已更改。

JSSWEB> select table_name,partition_name,high_value from user_tab_partitions

2       where table_name='T_PARTITION_RANGE';

TABLE_NAME                                     PARTITION_NAME                              HIGH_VALUE

------------------------------ ------------------------------ ----------------

T_PARTITION_RANGE                        T_RANGE_P3                                     30

T_PARTITION_RANGE                         T_RANGE_PMAX                                  MAXVALUE

T_PARTITION_RANGE                         T_RANGE_PNEW                                 20

JSSWEB> select *from t_partition_range partition(t_range_pnew);

ID NAME

---------- --------------------------------------------------

11  a

12  b

13  c

8 g

可見,合併分割槽操作不會造成資料丟失,另外如果你想為新分割槽指定屬性的話,在語句末尾處增加儲存屬性即可(如果不指定,則新分割槽預設繼續表的儲存屬性)。例如:

JSSWEB> select partition_name,high_value,tablespace_name from user_tab_partitions 2 where table_name='T_PARTITION_LIST';

PARTITION_NAME       HIGH_VALUE                                      TABLESPACE_NAME

--------------------              -------------------------------------------------- ---------------

T_LIST_P1    1, 2, 3, 4, 5, 6, 7, 8, 9, 10       TBSPART01 T_LIST_P2      11, 12, 13, 14, 15, 16, 17, 18, 19, 20    TBSPART02

T_LIST_P3                     21, 22, 23, 24, 25, 26, 27, 28, 29, 30         TBSPART03

         T_LIST_PD                     default                                                 TBSPART04

JSSWEB> alter table t_partition_list merge partitions t_list_p2,t_list_p3 2 into partition t_list_p2 tablespace tbspart02;

表已更改。

JSSWEB> select partition_name,high_value,tablespace_name from user_tab_partitions 2  where table_name='T_PARTITION_LIST';

PARTITION_NAME     HIGH_VALUE                                                        TABLESPACE_NAME

--------------------            --------------------------------------------------                   ---------------

T_LIST_P1                     1, 2, 3, 4, 5, 6, 7, 8, 9, 10                                      TBSPART01

T_LIST_P2                     21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 11, 12, 13       TBSPART02

, 14, 15, 16, 17, 18, 19, 20

T_LIST_PD                     default                                                               TBSPART04

注意,merge 分割槽操作與 coalesce 分割槽操作一樣,視被合併的分割槽資料量多少,都可能涉及到大量的 IO 操作。

其它合併組合分割槽的操作與上類似,如果要合併組合分割槽,注意關鍵字是 merge subpartitions,這裡就

不做演示了。

6、修改 list 表分割槽--AddValues

從標題即可得知,此命令僅應用於 list 分割槽或 list 子分割槽,語法也非常簡單:

Alter table tbname modify partition/subpartition ptname add values (v1,v2....vn); 舉個例子:

JSSWEB> select partition_name,high_value from user_tab_partitions

2       where table_name='T_PARTITION_LIST';

PARTITION_NAME            HIGH_VALUE

-------------------- --------------------------------------------------

T_LIST_P1                     1, 2, 3, 4, 5, 6, 7, 8, 9, 10

T_LIST_P2                     21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 11, 12, 13

, 14, 15, 16, 17, 18, 19, 20

T_LIST_PD                     default

JSSWEB> alter table t_partition_list modify partition t_list_p1 add values (31,33);

表已更改。

JSSWEB> select partition_name,high_value from user_tab_partitions 2  where table_name='T_PARTITION_LIST';

         PARTITION_NAME            HIGH_VALUE

-------------------- --------------------------------------------------

          T_LIST_P1                     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 31, 33

          T_LIST_P2                     21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 11, 12, 13

 

, 14, 15, 16, 17, 18, 19, 20

T_LIST_PD

default

唯一的限制是注意要新增的新 value 值不能存在於當前任何分割槽中,並且當前表也不能存在記錄值為新值的記錄,特別是當你建立了 default 分割槽的時候,有必要先檢查一下當前表不存在要新增的值,不然命令執行會出錯,例如:

JSSWEB> insert into t_partition_list values (32,'a');

已建立 1 行。

JSSWEB> alter table t_partition_list modify partition t_list_p1 add values (32); alter table t_partition_list modify partition t_list_p1 add values (32)

*

1 行出現錯誤:

ORA-14324: 所要新增的值已存在於 DEFAULT 分割槽之中

提示,增加新的列表值不會影響到表中原有的記錄,因此不會對索引造成影響。

7、修改 list 表分割槽--Drop Values

與上類似,也是隻能應用於 list 分割槽,不過功能相反,該命令是用來刪除指定分割槽的 value 值,語法如

下:

Alter table tbname modify partition/subpartition ptname drop values (v1,v2....vn);

同樣在刪除 list 分割槽 value 列值的時候,也必須確認當前分割槽存在指定的 value 值,但是沒有任何應用

該值的記錄,有點兒饒是吧,腦袋多轉幾圈就好了。

舉個例子:

JSSWEB> alter table t_partition_list modify partition t_list_p1 drop values (31);

表已更改。

成功執行了是吧,接著來看

JSSWEB> alter table t_partition_list modify partition t_list_p1 drop values (31); alter table t_partition_list modify partition t_list_p1 drop values (31)

*

1 行出現錯誤:

ORA-14313: 31 不在分割槽 T_LIST_P1

出錯了吧,這是其中的一種錯誤情形,即前面說的,要確保當前分割槽中存在指定的 value 值,再往下看

JSSWEB> alter table t_partition_list modify partition t_list_p1 add values (31);

表已更改。

JSSWEB> insert into t_partition_list values (31,'b');

已建立 1 行。

JSSWEB> alter table t_partition_list modify partition t_list_p1 drop values (31); alter table t_partition_list modify partition t_list_p1 drop values (31)

*

1 行出現錯誤:

ORA-14518: 分割槽包含的某些行對應於已刪除的值

這是另外的一種錯誤情形,即要確保拆分分割槽的記錄中,沒有應用了指定 value 值的記錄。

8、拆分表分割槽(Split Partition) 如果你對我們前面講到過的merge partition 還有印象的話,那麼學習Split partition 也不會遇到什麼障礙,

split partition 的功能與 merge partition 功能正好相反:後者是將兩個全區合併成一個,前者則是將一個分割槽

拆分成兩個。其用途非常廣泛,比如通常見你發現某個分割槽過大,你就可以透過這種方式將該分割槽分解成多個小分割槽,對我而言最常用到的,當然還是 split maxvalue/default 的分割槽。

該命令的語法針對不同分割槽會有不同的形式,

l  For range partition alter table tbname split partition ptname at (value) into (partition newpt1 tbs_clause,partition newpt2 tbs_clause);

l  For list partition : alter table tbname split partition ptname values (v1,v2...vn) into (partition newpt1 tbs_clause,partition newpt2 tbs_clause);

上述兩項,如果是操作子分割槽,則將 partition 關鍵字換成 subpartition 即可。舊分割槽中符合新定義值的記錄會儲存到指定的第一個分割槽中,其它的記錄儲存到第二個分割槽。

例如,range 分割槽的示例:

JSSWEB> select partition_name,high_value,tablespace_name from user_tab_partitions

2       where table_name='T_PARTITION_RANGE';

PARTITION_NAME            HIGH_VALUE                                                      TABLESPACE_NAME

-------------------- ---------------------------------------- --------------------

T_RANGE_P3                   30                                                                    TBSPART03

T_RANGE_PMAXMAXVALUE  TBSPART04 T_RANGE_P120    TBSPART02

我們將 t_range_p1 分割槽分隔到兩個分割槽中,小於 10 的存放新建分割槽 t_range_p1(已非原 t_range_p1 鳥,

只是名稱相同而已),其它資料存入 t_range_p2 分割槽:

JSSWEB> alter table t_partition_range split partition t_range_p1 at (10) into

2       (partition t_range_p1 tablespace tbspart01,

3       partition t_range_p2 tablespace tbspart02);


表已更改。

JSSWEB> select partition_name,high_value,tablespace_name from user_tab_partitions

              2   where table_name='T_PARTITION_RANGE';

         PARTITION_NAME            HIGH_VALUE

TABLESPACE_NAME

-------------------- --------------

T_RANGE_P3

-------------------------- --------------------

30

TBSPART03

T_RANGE_PMAX

MAXVALUE

TBSPART04

T_RANGE_P1

10

TBSPART01

T_RANGE_P2

20

TBSPART02

再來演示一個 list 分割槽的例子:

JSSWEB> select partition_name,high_value,tablespace_name from user_tab_partitions 2 where table_name='T_PARTITION_LIST';

PARTITION_NAME            HIGH_VALUE                                                      TABLESPACE_NAME

-------------------- ---------------------------------------- --------------------

T_LIST_P1                     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 33              TBSPART01

T_LIST_P2                     21, 22, 23, 24, 25, 26, 27, 28, 29, 30,   TBSPART02

11, 12, 13, 14, 15, 16, 17, 18, 19, 20

T_LIST_PD                     default                                                           TBSPART04

我們將 t_list_p2 分割槽中分割槽值是 2 打頭的儲存到 t_list_p3 分割槽中,其它值儲存到 t_list_p2 分割槽:

JSSWEB> alter table t_partition_list split partition t_list_p2 values

2    (20,21,22,23,24,25,26,27,28,29) into

3    (partition t_list_p3 tablespace tbspart03, 4       partition t_list_p2);

表已更改。

JSSWEB> select partition_name,high_value,tablespace_name from user_tab_partitions 2  where table_name='T_PARTITION_LIST';

PARTITION_NAME            HIGH_VALUE                                                       TABLESPACE_NAME

-------------------- ---------------------------------------- --------------------

T_LIST_P1                     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 33              TBSPART01

T_LIST_P2                     30, 11, 12, 13, 14, 15, 16, 17, 18, 19     TBSPART02

T_LIST_PD                     default                                                           TBSPART04

T_LIST_P3                     20, 21, 22, 23, 24, 25, 26, 27, 28, 29     TBSPART03

提示:

lsplit partition/subpartition 不能用於 hash 分割槽或 hash 子分割槽(hash 的話,直接用 add partition 就好了) l split partition/subpartition 視被分隔的分割槽資料量多少,可能需要花費不小的代價,相當於該分割槽資料的全掃描,我們也許可以形容為:full partition scan:),除非:

n   Split 後的兩個分割槽中,至少有一個是空的,並且非空的那個分割槽的儲存屬性與 split 前的儲存屬性完全相同

n   如果 split 的分割槽包含 lob 欄位,split 後非空的那個分割槽中該欄位的儲存屬性也必須與 split 前的儲存屬性完全相同。

這種情況下的 split partition/subpartition 也會非常高效,oracle 會自動進行最佳化,此時的分割槽操作類似於 add partition

l通常情況下,如果在執行 split partition/subpartition 時,如果沒有指定 update indexes 子句,都會造成 local global 索引的失效。注意,我們說的是通常,如果你 split partition/subpartition 的是個空分割槽,或者沒有觸發任何資料移動或變化,那麼即使不加 update indexes,也不會影響到索引。當然,保險起見,建議你還是執行完之後,查詢一下資料字典,確認一下當前索引的狀態。

9、    截斷表分割槽(Truncate Partition)

Truncate partition 就像 truncate table 一樣,直接從頭部截斷資料,用來刪除資料那是效率超高無比。但是如果該表有外來鍵引用的話,ddl truncate 就不好使了,這時候你只能要麼使用 delete,要麼先 disable 掉外來鍵關聯再 truncate 了。同樣,在不指定 update indexes 子句的情況下,truncate partition 也會造成分割槽所在表的 global 索引失效。

語法非常簡單:alter table tbname truncate partition/subpartition ptname; 例如:

JSSWEB> select *from t_partition_range partition(t_range_p1);

ID NAME

---------- --------------------

11  a

12  b

13  c

JSSWEB> alter table t_partition_range truncate partition t_range_p1;

表被截斷。

JSSWEB> select *from t_partition_range partition(t_range_p1);

未選定行

10、              移動表分割槽(Move Partition)

Move partition modify partition 的功能相似,但又比之更加強勁,比如可以修改分割槽所在表空間等等,與 move table 的操作很類似,某些時間也非常有用,比如降低行遷移。語法很簡單:

Alter table tbname move partition/subpartition ptname .....;

例如:

JSSWEB> select partition_name,tablespace_name from user_tab_partitions

              2   where table_name='T_PARTITION_RANGE';

         PARTITION_NAME            TABLESPACE_NAME

-------------------- ---------------

T_RANGE_P3                   TBSPART03

T_RANGE_PMAX TBSPART04 T_RANGE_P1 WEBTBS

JSSWEB> alter table t_partition_range move partition t_range_p1 tablespace tbspart02;

表已更改。

JSSWEB> select partition_name,tablespace_name from user_tab_partitions

2       where table_name='T_PARTITION_RANGE';

PARTITION_NAME            TABLESPACE_NAME

-------------------- ---------------

T_RANGE_P3                   TBSPART03

T_RANGE_PMAX                TBSPART04

T_RANGE_P1                   TBSPART02

提示:move partition/subpartiton 時會鎖表,並且 move partition/subpartiton 視被移動分割槽中資料量的多

少,會帶來相應的 IO 操作。同時還需要注意,如果在 move partition/subpartiton 時沒有指定 update indexes 子句,則被移動分割槽所在的 local 索引以及全域性索引都會失效,需要手工 rebuilding

11、              重新命名錶分割槽(Rename Partition)

就是改名,跟改表名、改列名的操作目的是類似的,語法也很簡單:

Alter table tbname rename partition ptname to newptname;

舉個例子:

JSSWEB> select partition_name from user_tab_partitions where table_name='T_PARTITION_RANGE';

PARTITION_NAME

--------------------

T_RANGE_P3

T_RANGE_PMAX

T_RANGE_PNEW

JSSWEB> alter table t_partition_range rename partition t_range_pnew to t_range_p1;

表已更改。

JSSWEB> select partition_name from user_tab_partitions where table_name='T_PARTITION_RANGE'; PARTITION_NAME

--------------------

T_RANGE_P3

T_RANGE_PMAX

T_RANGE_P1

12、              修改表分割槽預設屬性(Modify DefaultAttributes)

修改表或表中分割槽的儲存引數,對當前表和分割槽的儲存引數沒有影響,只有修改過之後,當你下次再

新增分割槽時,在不手工顯式指定新分割槽引數的情況下,新分割槽預設使用你當前指定的儲存引數。

有兩種操作方式:

修改表屬性,適用於 range,list,hash 分割槽形式(注意 hash 分割槽只能修改預設表空間引數)。例如:

JSSWEB> alter table t_partition_list modify default attributes tablespace webtbs;

表已更改。

修改分割槽屬性,適用於組合分割槽,例如:

JSSWEB> alter table t_partition_rl modify default attributes for partition t_r_p2 tablespace webtbs;

表已更改。

13、              修改表分割槽當前屬性(Modify Partition)

與上不同,該命令修改的不是預設屬性,而是分割槽當前的儲存屬性,即修改即生效的那種,雖然號稱

是修改當前分割槽屬性,但實際上也有限制,比如所在表空間它就改不了(如果你想改,可以用 move partition,後面會講到)

儲存屬性呢,三思一向沒有過多關注(也許是因為從未有過因此導致的慘痛教訓),此節跳過,留待有心

人自行查詢文件:)

14、              修改表子分割槽模板(Set Subpartition Template)

既然是修改子分割槽模板,自然是隻針對複合分割槽有效。修改分割槽模式不會改變當前的分割槽結構,只有

當你再增加、合併分割槽並且未顯式指定子分割槽儲存引數時,才會繼承新分割槽模板中的引數。該命令語法很簡單:alter table tbname set subpartition template ....;

下面舉個例子:

JSSWEB> select subpartition_name,tablespace_name from user_subpartition_templates

2       where table_name='T_PARTITION_RH';

SUBPARTITION_NAME                                TABLESPACE_NAME

---------------------------------- ---------------

H1

TBSPART01

H2

TBSPART02

H3

TBSPART03

H4                                                          TBSPART04

JSSWEB> alter table t_partition_rh

2       set subpartition template(

3       subpartition h1 tablespace tbspart01,

4       subpartition h2 tablespace tbspart02,

5       subpartition h3 tablespace tbspart03);

表已更改。

JSSWEB> select subpartition_name,tablespace_name from user_subpartition_templates

2       where table_name='T_PARTITION_RH';

SUBPARTITION_NAME                                TABLESPACE_NAME

---------------------------------- ---------------

H1                                                          TBSPART01

H2                                                          TBSPART02

H3                                                          TBSPART03

*這裡又學到一個資料字典:user_subpartition_templates,用來查詢表的分割槽模板資訊。

如果說,想清除某表的分割槽模板,那就更簡單了:

JSSWEB> select subpartition_name,tablespace_name from user_subpartition_templates 2  where table_name='T_PARTITION_RL';

SUBPARTITION_NAME                                TABLESPACE_NAME

---------------------------------- ---------------

L1                                                          TBSPART01

L2                                                          TBSPART02

L3                                                          TBSPART03

L4                                                          TBSPART04

JSSWEB> alter table t_partition_rl set subpartition template();

表已更改。

JSSWEB> select * from user_subpartition_templates where table_name='T_PARTITION_RL';

未選定行

分割槽索引的管理

1、增加索引分割槽(Adding Index Partitions)

從語法上來講,增加索引分割槽與增加表分割槽沒有什麼實際性差別,將 table 換成 index 即可:

Alter index idxname add partition ptname tbs_clause;

需要注意一點 add partition 只能用於 hash global 索引(如果你想為 range 型別的索引增加分割槽,不要

add,split 也許能幫你實際你的需求),並且 add partition 無法新增 local 索引分割槽,因為 local 分割槽是由索引所在基表來維護的。

下面舉個操作的例子,還記的我們前面演示建立 hash 分割槽的時候建立的索引嗎,這裡就以它為例吧:

JSSWEB> select partition_name,tablespace_name from user_ind_partitions

2       where index_name='IDX_PART_HASH_ID';

PARTITION_NAME                              TABLESPACE_NAME

------------------------------ ------------------------------

SYS_P113                                        TBSPART01

SYS_P114                                        TBSPART02

SYS_P115                                        TBSPART03

JSSWEB> alter index idx_part_hash_idadd partition i_hash_id_p4 tablespace tbspart04;

索引已更改。

JSSWEB> select partition_name,tablespace_name from user_ind_partitions

2       where index_name='IDX_PART_HASH_ID';

PARTITION_NAME                              TABLESPACE_NAME

------------------------------ ------------------------------

I_HASH_ID_P4                                 TBSPART04

SYS_P113                                        TBSPART01

SYS_P114      TBSPART02 SYS_P115TBSPART03

看看,就是這麼簡單。

2、刪除索引分割槽(Dropping Index Partitions)

Drop partition 只能操作 global 索引的 range 分割槽,語法也很簡單:

Alter index idxname drop partition ptname;

看起來很簡單對吧,但是,需要注意,索引必須擁有一個 maxvalue 的分割槽,該分割槽無法刪除。另外,如果刪除的索引分割槽中包含資料,分割槽被刪除後,會造成相鄰的 higher 分割槽失效,需要手工編

譯!這個其實很容易理解,索引中資料都是經過排序的,我們 drop partition 刪除的只是分割槽,但其對應的索引資料還需要有地兒存在行啊(不然索引啟不就不準確了),於是就只好儲存到比它更高區間值的索引區分裡去了,那個分割槽莫名其妙多了資料,自然狀態就為不可用了。

舉個例子:


JSSWEB> select partition_name,high_value,tablespace_name,status from user_ind_partitions

2       where index_name='IDX_PART_RANGE_ID';

PARTITION_NAME             HIGH_VALUE          TABLESPACE_NAME          STATUS

-------------------- --------------- -------------------- --------

I_RANGE_P1                   10                         TBSPART01                     USABLE

I_RANGE_P240    TBSPART02   USABLE I_RANGE_PMAXMAXVALUE  TBSPART03   USABLE

向表中插入幾條記錄:

JSSWEB> insert into t_partition_range values (8,'a');

已建立 1 行。

JSSWEB> insert into t_partition_range values (9,'b');

已建立 1 行。

JSSWEB> commit;

提交完成。

執行刪除操作

JSSWEB> alter index idx_part_range_iddrop partition i_range_p1;

索引已更改。

JSSWEB> select partition_name,high_value,tablespace_name,status from user_ind_partitions 2      where index_name='IDX_PART_RANGE_ID';

PARTITION_NAME             HIGH_VALUE          TABLESPACE_NAME          STATUS

-------------------- --------------- -------------------- --------

I_RANGE_P240    TBSPART02   UNUSABLE I_RANGE_PMAX   MAXVALUE  TBSPART03   USABLE

於是,i_range_p2 分割槽就 unusable 了,繼續往下看吧,後面要講如何重編譯索引分割槽了。

3、重編譯索引分割槽(Rebuilding Index Partitions)

一生不如意,十有八九。碰上索引分割槽無效也不見得就是撞頭彩的運氣,這個東西還是黑常見的,比

如分割槽表操作時未指定 update indexes 子句就極有可能造成索引分割槽的無效,一般情況下,你都可以透過:

Alter index idxname rebuild partition/subpartition ptname;

重新編譯。注意 global 索引只支援 range 分割槽,local 索引無限制。

例如:

JSSWEB> alter index idx_part_range_idrebuildpartition i_range_p2;

索引已更改。

JSSWEB> select partition_name,high_value,tablespace_name,status from user_ind_partitions 2      where index_name='IDX_PART_RANGE_ID';

PARTITION_NAME             HIGH_VALUE          TABLESPACE_NAME          STATUS

-------------------- --------------- -------------------- --------

I_RANGE_P240    TBSPART02   USABLE I_RANGE_PMAXMAXVALUE  TBSPART03   USABLE

而對於 local 索引分割槽,你還可以使用這種命令方式:

alter table tbname modify partition/subpartition ptname rebuild unusable local indexes;

4、重新命名索引分割槽(Renaming Index Partitions)

與表分割槽中改名功能相同,索引分割槽重新命名也僅只是改個名字而已,語法非常簡單:

Alter index idxname rename partition/subpartition ptname to ptnewname;

這個功能沒啥可說的,使用也很簡單:

JSSWEB> alter index idx_part_range_id rename partition i_range_p2 to i_range_p1;

索引已更改。

同樣需要注意,global 分割槽只能夠支援 range 分割槽,local 索引無限制。

5、分拆索引分割槽(Splitting Index Partitions)

Split partiton 操作只能操作 global 索引分割槽(local 分割槽會自動維護),且只能操作 global 索引分割槽中 range 型別的分割槽。

語法與表分割槽的操作很類似:

Alter index idxname split partition ptname at(value) into(partition pt1 tbsclause,partition pt2 tbsclause);

看個例子:

JSSWEB> alter index idx_part_range_id split partition i_range_p1 at (10) into

2       (partition i_range_p1 tablespace tbspart01,

3       partition i_range_p2 tablespace tbspart02);

索引已更改。

JSSWEB> select partition_name,high_value,tablespace_name,status from user_ind_partitions 2      where index_name='IDX_PART_RANGE_ID';

PARTITION_NAME             HIGH_VALUE          TABLESPACE_NAME          STATUS

-------------------- --------------- -------------------- --------

         I_RANGE_P1                   10                         TBSPART01

USABLE

          I_RANGE_PMAX                MAXVALUE              TBSPART03

USABLE

         I_RANGE_P2                   40                         TBSPART02

USABLE

6、修改索引分割槽預設屬性(Modifying Default Attributes of Index Partitions)

修改索引分割槽預設屬性,與修改表分割槽的操作沒什麼區別,不過對於 global 索引,你只能修改 range 分割槽,local 索引則無此限制。

語法上小有差異:Alter index idxname modify default attributes for partition ptname; 不做演示!

7、修改索引分割槽當前屬性(Modifying Real Attributes of Index Partitions)

同樣 global 索引只支援 range 分割槽的修改,支援所有 local 索引,其它與表分割槽修改同理,不做演示!

全篇完結之後記

原計劃還想花重量篇幅多介紹一些實踐,比如分割槽表的常見使用方式,對於效率提升的比較,不同情況下,使用 global 索引與 local 索引的區別,什麼情況下會造成索引失效,什麼時候需要重新編譯等待~~~待到行筆處卻發現千言萬語,又不知從何處開始。

越學越覺著 oracle 博大精深,確實不是蓋的,小小一個分割槽就能引出這麼多文章,還無法一一道進。因此,原計劃起的深入學習分割槽表分割槽表及分割槽索引寫到最後也是越寫也沒自信,越寫越覺著我所瞭解到的和我所能介紹的不過都是皮毛罷了,因此,改名吧。。。全面認識 oracle 分割槽表及分割槽索引就此登場~

本系列全文已打包處理為 pdf,並上傳至 pub 論壇:http://www.itpub.net/996554.html,供有心者參閱方便~~

全文不過一家之言,雖在成文之前也多有參考前輩們的精華,但未免仍有紕漏,如有問題,歡迎大家就此與我溝通,交流。

 





About Me

...............................................................................................................................

● 本文來自於三思筆記

● 本文在itpub(http://blog.itpub.net/26736162)、部落格園(http://www.cnblogs.com/lhrbest)和個人微信公眾號(xiaomaimiaolhr)上有同步更新

● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/

● 本文部落格園地址:http://www.cnblogs.com/lhrbest

● 本文pdf版及小麥苗雲盤地址:http://blog.itpub.net/26736162/viewspace-1624453/

● 資料庫筆試面試題庫及解答:http://blog.itpub.net/26736162/viewspace-2134706/

● QQ群:230161599     微信群:私聊

● 聯絡我請加QQ好友(646634621),註明新增緣由

● 於 2017-07-01 09:00 ~ 2017-07-31 22:00 在魔都完成

● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解

● 版權所有,歡迎分享本文,轉載請保留出處

...............................................................................................................................

拿起手機使用微信客戶端掃描下邊的左邊圖片來關注小麥苗的微信公眾號:xiaomaimiaolhr,掃描右邊的二維碼加入小麥苗的QQ群,學習最實用的資料庫技術。

【三思筆記】 全面學習Oracle分割槽表及分割槽索引
DBA筆試面試講解
歡迎與我聯絡

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

相關文章