關于分區表和分區索引(About Partitioned Tables and Indexes)對于10gR2而言,基本上可以分成幾類:
- Range(范圍)分區
- Hash(哈希)分區
- List(列表)分區
- 以及組合分區:Range-Hash,Range-List。
對于表而言(常規意義上的堆組織表),上述分區形式都可以應用(甚至可以對某個分區指定compress屬性),只不過分區依賴列不能是lob,long之類數據類型,每個表的分區或子分區數的總數不能超過1023個。
對于索引組織表,只能夠支持普通分區方式,不支持組合分區,常規表的限制對于索引組織表同樣有效,除此之外呢,還有一些其實的限制,比如要求索引組織表的分區依賴列必須是主鍵才可以等。
注:本篇所有示例僅針對常規表,即堆組織表!
對于索引,需要區分創建的是全局索引,或本地索引:
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-hash,range-list。注意順序喲,根分區只能是range分區,子分區可以是hash分區或list分區。
提示:11g在組合分區功能這塊有所增強,又推出了range-range,list-range,list-list,list-hash,這就相當于除hash外三種分區方式的笛卡爾形式都有了。為什么會沒有hash做為根分區的組合分區形式呢,再仔細回味一下第二點,你一定能夠想明白~~。
一、如何創建
如果想對某個表做分區,必須在創建表時就指定分區,我們可以對一個包含分區的表中的分區做修改,但不能直接將一個未分區的表修改成分區表(起碼在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,
5 partition 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'
3 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
|
創建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_indexes、user_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
|
創建hash分區
語法如下:[圖:hash_partitioning.gif]

語法看起來比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); |
索引已創建。
查詢索引的分區信息也仍是通過user_part_indexes、user_ind_partitions兩個數據字典,不再舉例。
③ 創建Local索引
在前面學習range分區時,我們已經對Local索引的特性做了非常清晰的概述,因此這里也不再舉例,如有疑問,建議再仔細復習range分區的相關示例,如果還有疑問,當面問我好了:)
綜上:
Ø 對于global索引分區而言,在10g中只能支持range分區和hash分區,因此后續示例中不會再提及。
Ø 對于local索引分區而言,其分區形式完全依賴于索引所在表的分區形式,不管從創建語法還是理解難度均無技術含量,因此后續也不再提供示例。
Ø 注意,在創建索引時如果不顯式指定global或local,則默認是global。
Ø 注意,在創建global索引時如果不顯式指定分區子句,則默認不分區(廢話)。
全面學習Oracle分區表及分區索引(4)-創建list分區
創建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分區顯然不好用啊~~~