Oracle分割槽表及分割槽索引
關於分割槽表和分割槽索引(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。
ORACLE對於分割槽表方式其實就是將表分段儲存,一般普通表格是一個段存 儲,而分割槽表會分成多個段,所以查詢資料過程都是先定位根據查詢條件定位分割槽範圍,即資料在那個分割槽或那幾個內部,然後在分割槽內部去查詢資料,一個分割槽一 般保證四十多萬條資料就比較正常了,但是分割槽表並非亂建立,而其維護性也相對較為複雜一點,而索引的建立也是有點講究的,這些以下儘量闡述詳細即可。
range分割槽方式,也算是最常用的分割槽方式,其透過某欄位或幾個欄位的組合的值,從小到大,按照指定的範圍說明進行分割槽,我們在INSERT資料的時候就會儲存到指定的分割槽中。
List分割槽方式,一般是在range基礎上做的二級分割槽較多,是一種列舉方式進行分割槽,一般講某些地區、狀態或指定規則的編碼等進行劃分。
Hash分割槽方式,它沒有固定的規則,由ORACLE管理,只需要將值INSERT進去,ORACLE會自動去根據一套HASH演算法去劃分分割槽,只需要告訴ORACLE要分幾個區即可。
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做為根分割槽的組合分割槽形式呢,再仔細回味一下第二點,你一定能夠想明 白~~。
深入學習Oracle分割槽表及分割槽索引(2)
一、如何建立
如果想對某個表做分割槽,必須在建立表時就指定分割槽,我們可以對一個包含分割槽的表中的分割槽做修改,但不能直接將一個未分割槽的表修改成分割槽表(起碼在10g是不行的,當然你可能會說,可以透過線上重定義的方式,但是這不是直接喲,這也是藉助臨時表間接實現的)。
建立表或索引的語法就不說了,大家肯定比我還熟悉,而想在建表(索引)同時指定分割槽也非常容易,只需要把建立分割槽的子句放到";"前就行啦,同 時需要注意表的row movement屬性,它用來控制是否允許修改列值所造成的記錄移動至其它分割槽儲存,有enable|disable兩種狀態,預設是disable row movement,當disable時,如果記錄要被更新至其它分割槽,則更新語句會報錯。
下面分別演示不同分割槽方式的表和索引的建立:
1、建立range分割槽
語法如下,需要我們指定的有:
l column:分割槽依賴列(如果是多個,以逗號分隔);
l partition:分割槽名稱;
l values less than:後跟分割槽範圍值(如果依賴列有多個,範圍對應值也應是多個,中間以逗號分隔);
l tablespace_clause:分割槽的儲存屬性,例如所在表空間等屬性(可為空),預設繼承基表所在表空間的屬性。
① 建立一個標準的range分割槽表:
JSSWEB> create table t_partition_range (id number,name varchar2(50))
partition by range(id)(
partition t_range_p1 values less than (10) tablespace tbspart01,
partition t_range_p2 values less than (20) tablespace tbspart02,
partition t_range_p3 values less than (30) tablespace tbspart03,
partition t_range_pmax values less than (maxvalue) tablespace tbspart04
);
表已建立。
要查詢建立分割槽的資訊,可以透過查詢user_part_tables,user_tab_partitions兩個資料字典(索引分割槽、組織分割槽等資訊也有對應的資料字典,後續示例會逐步提及)。
user_part_tables:記錄分割槽的表的資訊;
user_tab_partitions:記錄表的分割槽的資訊。
例如:
JSSWEB> select table_name,partitioning_type,partition_count
From user_part_tables where table_name='T_PARTITION_RANGE';
JSSWEB> select partition_name,high_value,tablespace_name
from user_tab_partitions where table_name='T_PARTITION_RANGE'
order by partition_position;
② 建立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';
③ 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';
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;
可以看出,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';
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;
建立hash分割槽
語法如下:[圖:hash_partitioning.gif]
語法看起來比range複雜,其實使用起來比range更簡單,這裡需要我們指定的有:
l column:分割槽依賴列(支援多個,中間以逗號分隔);
l partition:指定分割槽,有兩種方式:
n 直接指定分割槽名,分割槽所在表空間等資訊
n 只指定分割槽數量,和可供使用的表空間。
2、建立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索引時如果不顯式指定分割槽子句,則預設不分割槽(廢話)。
3、分割槽應用:
一般一張表超過2G的大小,ORACLE是推薦使用分割槽表的,分割槽一般都需要 建立索引,說到分割槽索引,就可以分為:全域性索引、分割槽索引,即:global索引和local索引,前者為預設情況下在分割槽表上建立索引時的索引方式,並 不對索引進行分割槽(索引也是表結構,索引大了也需要分割槽,關於索引以後專門寫點)而全域性索引可修飾為分割槽索引,但是和local索引有所區別,前者的分割槽 方式完全按照自定義方式去建立,和表結構完全無關,所以對於分割槽表的全域性索引有以下兩幅網上常用的圖解:
3.1、對於分割槽表的不分割槽索引(這個有點繞,不過就是表分割槽,但其索引不分割槽):
建立語法(直接建立即可):
CREATE INDEX ON ();
3.2、對於分割槽表的分割槽索引:
建立語法為:
CREATE INDEX 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)
);
3.3、LOCAL索引結構:
建立語法為:
CREATE INDEX INX_TAB_PARTITION_COL1 ON TABLE_PARTITION(COL1) LOCAL;
也可按照分割槽表的的分割槽結構給與一一定義,索引的分割槽將得到重新命名。
分割槽上的點陣圖索引只能為LOCAL索引,不能為GLOBAL全域性索引。
3.4、對比索引方式:
一般使用LOCAL索引較為方便,而且維護代價較低,並且LOCAL索引是在分割槽的基礎上去建立索引,類似於在一個子表內部去建立索引,這樣開銷主要是區 分分割槽上,很規範的管理起來,在OLAP系統中應用很廣泛;而相對的GLOBAL索引是全域性型別的索引,根據實際情況可以調整分割槽的類別,而並非按照分割槽 結構一一定義,相對維護代價較高一些,在OLTP環境用得相對較多,這裡所謂OLTP和OLAP也是相對的,不是特殊的專案,沒有絕對的劃分概念,在應用 過程中依據實際情況而定,來提高整體的執行效能。
4、常用檢視:
1、查詢當前使用者下有哪些是分割槽表:
SELECT * FROM USER_PART_TABLES;
2、查詢當前使用者下有哪些分割槽索引:
SELECT * FROM USER_PART_INDEXES;
3、查詢當前使用者下分割槽索引的分割槽資訊:
SELECT * FROM USER_IND_PARTITIONS T
WHERE T.INDEX_NAME=?
4、查詢當前使用者下分割槽表的分割槽資訊:
SELECT * FROM USER_TAB_PARTITIONS T
WHERE T.TABLE_NAME=?;
5、查詢某分割槽下的資料量:
SELECT COUNT(*) FROM TABLE_PARTITION PARTITION(TAB_PARTOTION_01);
6、查詢索引、表上在那些列上建立了分割槽:
SELECT * FROM USER_PART_KEY_COLUMNS;
7、查詢某使用者下二級分割槽的資訊(只有建立了二級分割槽才有資料):
SELECT * FROM USER_TAB_SUBPARTITIONS;
5、維護操作:
5.1、刪除分割槽
ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_03;
如果是全域性索引,因為全域性索引的分割槽結構和表可以不一致,若不一致的情況下,會導致整個全域性索引失效,在刪除分割槽的時候,語句修改為:
ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_03 UPDATE GLOBAL INDEXES;
5.2、分割槽合併(從中間刪除掉一個分割槽,或者兩個分割槽需要合併後減少分割槽數量)
合併分割槽和刪除中間的RANGE有點像,但是合併分割槽是不會刪除資料的,對於LIST、HASH分割槽也是和RANGE分割槽不一樣的,其語法為:
ALTER TABLE TABLE_PARTITION MERGE PARTITIONS TAB_PARTOTION_01,TAB_PARTOTION_02 INTO PARTITION MERGED_PARTITION;
5.3、分隔分割槽(一般分割槽從擴充套件分割槽從分隔)
ALTER TABLE TABLE_PARTITION SPLIT PARTITION TAB_PARTOTION_OTHERE AT(2500000)
INTO (PARTITION TAB_PARTOTION_05,PARTITION TAB_PARTOTION_OTHERE);
5.4、建立新的分割槽(分割槽資料若不能提供範圍,則插入時會報錯,需要增加分割槽來擴大範圍)
一般有擴充套件分割槽的是都是用分隔的方式,若上述建立表時沒有建立TAB_PARTOTION_OTHER分割槽時,在插入資料較大時(按照上述建立規則,超過1800000就應該建立新的分割槽來儲存),就可以建立新的分割槽,如:
為了試驗,我們將擴充套件分割槽先刪除掉再建立新的分割槽(因為ORACLE要求,分割槽的資料不允許重疊,即按照分割槽欄位同樣的資料不能同時儲存在不同的分割槽中):
ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_OTHER;
ALTER TABLE TABLE_PARTITION ADD PARTITION TAB_PARTOTION_06 VALUES LESS THAN(2500000);
在分割槽下建立新的子分割槽大致如下(RANGE分割槽,若為LIST或HASH分割槽,將建立方式修改為對應的方式即可):
ALTER TABLE MODIFY PARTITION ADD SUBPARTITION VALUES LESS THAN(....);
5.5、修改分割槽名稱(修改相關的屬性資訊)
ALTER TABLE TABLE_PARTITION RENAME PARTITION MERGED_PARTITION TO MERGED_PARTITION02;
5.6、交換分割槽(快速交換資料,其實是交換段名稱指標)
首先建立一個交換表,和原表結構相同,如果有資料,必須符合所交換對應分割槽的條件:
CREATE TABLE TABLE_PARTITION_2
AS SELECT * FROM TABLE_PARTITION WHERE 1=2;
然後將第一個分割槽的資料交換出去:
ALTER TABLE TABLE_PARTITION EXCHANGE PARTITION TAB_PARTOTION_01
WITH TABLE TABLE_PARTITION_2 INCLUDING INDEXES;
此時會發現第一個分割槽的資料和表TABLE_PARTITION_2做了瞬間交換,比TRUNCATE還要快,因為這個過程沒有進行資料轉存,只是段名稱的修改過程,和實際的資料量沒有關係。
如果是子分割槽也可以與外部的表進行交換,只需要將關鍵字修改為:SUBPARTITION 即可。
5.7、清空分割槽資料
ALTER TABLE TRUNCATE PARTITION ;
ALTER TABLE TRUNCATE subpartition ;
6、磁碟碎片壓縮
對分割槽表的某分割槽進行磁碟壓縮,當對分割槽內部資料進行了大量的UPDATE、DELETE操作後,一定時間需要進行磁碟壓縮,否則在查詢時,若透過FULL SCAN掃描資料,將會把空塊也會掃描到,對錶進行磁碟壓縮需要進行行遷移操作,所以首先需要操作:
ALTER TABLE ENABLE ROW MOVEMENT ;
對分割槽表的某分割槽壓縮語法為:
ALTER TABLE
modify partition shrink space;
對普通表壓縮:
ALTER TABLE shrink space;
對於索引也需要進行壓縮,索引也是表:
ALTER INDEX shrink space;
7、分割槽表重新分析以及索引重新分析
對錶進行壓縮後,需要對錶和索引進行重新分析,對錶進行重新分析,一般有兩種方式:
在ORACLE 10G以前,使用:
BEGIN
dbms_stats.gather_table_stats(USER,UPPER(''));
END;
ORACLE 10G後,可以使用:
ANALYZE TABLE COMPUTE STATISTICS;
索引重新分析,將上述兩種方式分別修改一下,如第一種可以使用:gather_index_stats,而第二種修改為:ANALYZE INDEX即可,不過一般比較常用的是重新編譯:
對於分割槽表並進行了索引分割槽的情況,需要對每個分割槽的索引進行重新編譯,這裡以LOCAL索引為例子(其每個索引的分割槽和表分割槽結構相同,預設分割槽名稱和表分割槽名稱相同):
ALTER INDEX REBUILD PARTITION ;
對於全域性索引,根據全域性索引鎖定義的分割槽名稱修改即可,若沒有分割槽,和普通單表索引重新編譯方式相同:
ALTER INDEX REBUILD;
1、關聯物件重新編譯
上述對錶、索引進行重新編譯,尤其對錶進行了壓縮後會產生行遷移,這個過程可能會導致一些檢視、過程物件的失效,此時要將其重新編譯一次。
2、擴充套件:HASH分割槽中,如果建立了新的分割槽,可以將其進行重新HASH分佈:
ALTER TABLE COALESCA PARTITION
8、迴歸總結:何時建分割槽,分割槽類別,索引,如何對應SQL
1、建立時機
上述已經說明,2G以上的表,ORACLE推薦建立分割槽。
分割槽的方式根據實際情況而定,才能提高整體效能。
分割槽的欄位一定要是經常用以提取資料的欄位,否則會在提取過程中導致遍歷多個分割槽,這樣比沒有分割槽還要慢。
分割槽欄位要選擇合適,資料較為均勻分佈到各個分割槽,不要太多也不要太少,而且根據分割槽欄位可以很快定位到分割槽範圍。
一般情況下,儘量然業務操作在同一個分割槽內部完成。
2、分割槽類別
分割槽主要有RANGE、LIST、HASH;
RANGE透過值的範圍分割槽,也是最常用的分割槽,這種分割槽注意在一種變長數字字串中,很多人會導致認為是數字型別,而按照數字區分割槽,這樣會分佈十分不均勻的現象發生。
LIST是列舉方式進行分割槽,一般作為二級分割槽而存在(當然也可以自己分割槽,ORACLE 11G後在分割槽上也可以作為主分割槽而存在),在RANGE基礎上,若資料需要繼續分割槽,並且在RANGE基礎上資料量較為固定,只是較大,可以按照一定規則進一步分割槽。
HASH只指定分割槽個數,分割槽細節由ORACLE完成,增加HASH分割槽可以重新分佈資料。
注意:分割槽欄位不能使用函式轉換後在分割槽,如,將某數字字串欄位,先TO_NUMER(COL_NAME)後分割槽。
3、索引類別
大致分:GLOBAL索引和LOCAL索引,錢和可以分:GLOBAL不分割槽索引,和GLOBAL分割槽索引。
GLOBAL不分割槽索引一般不太推薦,因為是用一顆大的索引樹來對映一個表,這個過程,這樣速度不見得比不分割槽快。
GLOBAL分割槽索引,查詢資料若透過要透過索引,是先定位了索引內部的分割槽,然後在這個分割槽索引中找到ROWID,然後回表提取資料。
LOCAL索引是和分割槽的個數逐個對應的,可以說先定位分割槽表的分割槽也可以說先定位索引的分割槽,因為他們是一一對應的,找到對應分割槽後,分割槽內部索引資料集合。
4、對應應用
分割槽表、索引、分割槽索引,要利用其效能優勢,最基本就是要提取資料時,要透過它首先將資料的範圍縮小到一個即使做全盤掃描也不會太慢的情況。
所以SQL一定要有分割槽上的這個欄位的一個WHERE條件,將資料迅速定位到分割槽內部,而且儘量定位到一個分割槽裡面(這個和建立分割槽的規則有關係)。
建立分割槽本身不提要效能,要用好才可提高效能,在必要的RAC叢集中,若存在多分割槽提取資料,適當採用並行提取可以提高提取的速度。
對於索引部分,這裡也只提到分割槽索引的建立方式以及常見索引的維護方式,對於索引原理理解後會更容易認識到提取資料時的技巧。
9、實戰
分割槽表和一般表一樣可以建立索引,分割槽表可以建立區域性索引和全域性索引。當分割槽中出現許多事務並且要保證所有分割槽中的資料記錄的唯一性時採用全域性索引。
1 區域性索引分割槽的建立:
SQL> create index dinya_idx_t on dinya_test(item_id)
2 local
3 (
4 partition idx_1 tablespace dinya_space01,
5 partition idx_2 tablespace dinya_space02,
6 partition idx_3 tablespace dinya_space03
7 );
Index created.
SQL>
看查詢的執行計劃,從下面的執行計劃可以看出,系統已經使用了索引:
SQL> select * from dinya_test partition(part_01) t where t.item_id=12;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=187)
1 0 TABLE ACCESS (BY LOCAL INDEX ROWID) OF 'DINYA_TEST' (Cost=
2 Card=1 Bytes=187)
2 1 INDEX (RANGE SCAN) OF 'DINYA_IDX_T' (NON-UNIQUE) (Cost=1
Card=1)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
334 bytes sent via SQL*Net to client
309 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
2 rows processed
SQL>
2 全域性索引分割槽的建立。
全域性索引建立時global 子句允許指定索引的範圍值,這個範圍值為索引欄位的範圍值:
SQL> create index dinya_idx_t on dinya_test(item_id)
2 global partition by range(item_id)
3 (
4 partition idx_1 values less than (1000) tablespace dinya_space01,
5 partition idx_2 values less than (10000) tablespace dinya_space02,
6 partition idx_3 values less than (maxvalue) tablespace dinya_space03
7 );
Index created.
SQL>
本例中對錶的item_id欄位建立索引分割槽,當然也可以不指定索引分割槽名直接對整個表建立索引,如:
SQL> create index dinya_idx_t on dinya_test(item_id);
Index created.
SQL>
同樣的,對全域性索引根據執行計劃可以看出索引已經可以使用:
SQL> select * from dinya_test t where t.item_id=12;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=3 Bytes=561)
1 0 TABLE ACCESS (BY GLOBAL INDEX ROWID) OF 'DINYA_TEST' (Cost
=2 Card=3 Bytes=561)
2 1 INDEX (RANGE SCAN) OF 'DINYA_IDX_T' (NON-UNIQUE) (Cost=1
Card=3)
Statistics
----------------------------------------------------------
5 recursive calls
0 db block gets
10 consistent gets
0 physical reads
0 redo size
420 bytes sent via SQL*Net to client
309 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
5 rows processed
SQL>
其實分割槽的管理很簡單,難點在於分割槽方式的選擇和分割槽表上面索引的選擇。
Global Index全域性索引和Local Index區域性索引,Global partitioned index和global nonpartitioned index,
選擇多,就越迷惑。
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。
ORACLE對於分割槽表方式其實就是將表分段儲存,一般普通表格是一個段存 儲,而分割槽表會分成多個段,所以查詢資料過程都是先定位根據查詢條件定位分割槽範圍,即資料在那個分割槽或那幾個內部,然後在分割槽內部去查詢資料,一個分割槽一 般保證四十多萬條資料就比較正常了,但是分割槽表並非亂建立,而其維護性也相對較為複雜一點,而索引的建立也是有點講究的,這些以下儘量闡述詳細即可。
range分割槽方式,也算是最常用的分割槽方式,其透過某欄位或幾個欄位的組合的值,從小到大,按照指定的範圍說明進行分割槽,我們在INSERT資料的時候就會儲存到指定的分割槽中。
List分割槽方式,一般是在range基礎上做的二級分割槽較多,是一種列舉方式進行分割槽,一般講某些地區、狀態或指定規則的編碼等進行劃分。
Hash分割槽方式,它沒有固定的規則,由ORACLE管理,只需要將值INSERT進去,ORACLE會自動去根據一套HASH演算法去劃分分割槽,只需要告訴ORACLE要分幾個區即可。
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做為根分割槽的組合分割槽形式呢,再仔細回味一下第二點,你一定能夠想明 白~~。
深入學習Oracle分割槽表及分割槽索引(2)
一、如何建立
如果想對某個表做分割槽,必須在建立表時就指定分割槽,我們可以對一個包含分割槽的表中的分割槽做修改,但不能直接將一個未分割槽的表修改成分割槽表(起碼在10g是不行的,當然你可能會說,可以透過線上重定義的方式,但是這不是直接喲,這也是藉助臨時表間接實現的)。
建立表或索引的語法就不說了,大家肯定比我還熟悉,而想在建表(索引)同時指定分割槽也非常容易,只需要把建立分割槽的子句放到";"前就行啦,同 時需要注意表的row movement屬性,它用來控制是否允許修改列值所造成的記錄移動至其它分割槽儲存,有enable|disable兩種狀態,預設是disable row movement,當disable時,如果記錄要被更新至其它分割槽,則更新語句會報錯。
下面分別演示不同分割槽方式的表和索引的建立:
1、建立range分割槽
語法如下,需要我們指定的有:
l column:分割槽依賴列(如果是多個,以逗號分隔);
l partition:分割槽名稱;
l values less than:後跟分割槽範圍值(如果依賴列有多個,範圍對應值也應是多個,中間以逗號分隔);
l tablespace_clause:分割槽的儲存屬性,例如所在表空間等屬性(可為空),預設繼承基表所在表空間的屬性。
① 建立一個標準的range分割槽表:
JSSWEB> create table t_partition_range (id number,name varchar2(50))
partition by range(id)(
partition t_range_p1 values less than (10) tablespace tbspart01,
partition t_range_p2 values less than (20) tablespace tbspart02,
partition t_range_p3 values less than (30) tablespace tbspart03,
partition t_range_pmax values less than (maxvalue) tablespace tbspart04
);
表已建立。
要查詢建立分割槽的資訊,可以透過查詢user_part_tables,user_tab_partitions兩個資料字典(索引分割槽、組織分割槽等資訊也有對應的資料字典,後續示例會逐步提及)。
user_part_tables:記錄分割槽的表的資訊;
user_tab_partitions:記錄表的分割槽的資訊。
例如:
JSSWEB> select table_name,partitioning_type,partition_count
From user_part_tables where table_name='T_PARTITION_RANGE';
JSSWEB> select partition_name,high_value,tablespace_name
from user_tab_partitions where table_name='T_PARTITION_RANGE'
order by partition_position;
② 建立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';
③ 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';
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;
可以看出,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';
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;
建立hash分割槽
語法如下:[圖:hash_partitioning.gif]
語法看起來比range複雜,其實使用起來比range更簡單,這裡需要我們指定的有:
l column:分割槽依賴列(支援多個,中間以逗號分隔);
l partition:指定分割槽,有兩種方式:
n 直接指定分割槽名,分割槽所在表空間等資訊
n 只指定分割槽數量,和可供使用的表空間。
2、建立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索引時如果不顯式指定分割槽子句,則預設不分割槽(廢話)。
3、分割槽應用:
一般一張表超過2G的大小,ORACLE是推薦使用分割槽表的,分割槽一般都需要 建立索引,說到分割槽索引,就可以分為:全域性索引、分割槽索引,即:global索引和local索引,前者為預設情況下在分割槽表上建立索引時的索引方式,並 不對索引進行分割槽(索引也是表結構,索引大了也需要分割槽,關於索引以後專門寫點)而全域性索引可修飾為分割槽索引,但是和local索引有所區別,前者的分割槽 方式完全按照自定義方式去建立,和表結構完全無關,所以對於分割槽表的全域性索引有以下兩幅網上常用的圖解:
3.1、對於分割槽表的不分割槽索引(這個有點繞,不過就是表分割槽,但其索引不分割槽):
建立語法(直接建立即可):
CREATE INDEX
3.2、對於分割槽表的分割槽索引:
建立語法為:
CREATE INDEX 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)
);
3.3、LOCAL索引結構:
建立語法為:
CREATE INDEX INX_TAB_PARTITION_COL1 ON TABLE_PARTITION(COL1) LOCAL;
也可按照分割槽表的的分割槽結構給與一一定義,索引的分割槽將得到重新命名。
分割槽上的點陣圖索引只能為LOCAL索引,不能為GLOBAL全域性索引。
3.4、對比索引方式:
一般使用LOCAL索引較為方便,而且維護代價較低,並且LOCAL索引是在分割槽的基礎上去建立索引,類似於在一個子表內部去建立索引,這樣開銷主要是區 分分割槽上,很規範的管理起來,在OLAP系統中應用很廣泛;而相對的GLOBAL索引是全域性型別的索引,根據實際情況可以調整分割槽的類別,而並非按照分割槽 結構一一定義,相對維護代價較高一些,在OLTP環境用得相對較多,這裡所謂OLTP和OLAP也是相對的,不是特殊的專案,沒有絕對的劃分概念,在應用 過程中依據實際情況而定,來提高整體的執行效能。
4、常用檢視:
1、查詢當前使用者下有哪些是分割槽表:
SELECT * FROM USER_PART_TABLES;
2、查詢當前使用者下有哪些分割槽索引:
SELECT * FROM USER_PART_INDEXES;
3、查詢當前使用者下分割槽索引的分割槽資訊:
SELECT * FROM USER_IND_PARTITIONS T
WHERE T.INDEX_NAME=?
4、查詢當前使用者下分割槽表的分割槽資訊:
SELECT * FROM USER_TAB_PARTITIONS T
WHERE T.TABLE_NAME=?;
5、查詢某分割槽下的資料量:
SELECT COUNT(*) FROM TABLE_PARTITION PARTITION(TAB_PARTOTION_01);
6、查詢索引、表上在那些列上建立了分割槽:
SELECT * FROM USER_PART_KEY_COLUMNS;
7、查詢某使用者下二級分割槽的資訊(只有建立了二級分割槽才有資料):
SELECT * FROM USER_TAB_SUBPARTITIONS;
5、維護操作:
5.1、刪除分割槽
ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_03;
如果是全域性索引,因為全域性索引的分割槽結構和表可以不一致,若不一致的情況下,會導致整個全域性索引失效,在刪除分割槽的時候,語句修改為:
ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_03 UPDATE GLOBAL INDEXES;
5.2、分割槽合併(從中間刪除掉一個分割槽,或者兩個分割槽需要合併後減少分割槽數量)
合併分割槽和刪除中間的RANGE有點像,但是合併分割槽是不會刪除資料的,對於LIST、HASH分割槽也是和RANGE分割槽不一樣的,其語法為:
ALTER TABLE TABLE_PARTITION MERGE PARTITIONS TAB_PARTOTION_01,TAB_PARTOTION_02 INTO PARTITION MERGED_PARTITION;
5.3、分隔分割槽(一般分割槽從擴充套件分割槽從分隔)
ALTER TABLE TABLE_PARTITION SPLIT PARTITION TAB_PARTOTION_OTHERE AT(2500000)
INTO (PARTITION TAB_PARTOTION_05,PARTITION TAB_PARTOTION_OTHERE);
5.4、建立新的分割槽(分割槽資料若不能提供範圍,則插入時會報錯,需要增加分割槽來擴大範圍)
一般有擴充套件分割槽的是都是用分隔的方式,若上述建立表時沒有建立TAB_PARTOTION_OTHER分割槽時,在插入資料較大時(按照上述建立規則,超過1800000就應該建立新的分割槽來儲存),就可以建立新的分割槽,如:
為了試驗,我們將擴充套件分割槽先刪除掉再建立新的分割槽(因為ORACLE要求,分割槽的資料不允許重疊,即按照分割槽欄位同樣的資料不能同時儲存在不同的分割槽中):
ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_OTHER;
ALTER TABLE TABLE_PARTITION ADD PARTITION TAB_PARTOTION_06 VALUES LESS THAN(2500000);
在分割槽下建立新的子分割槽大致如下(RANGE分割槽,若為LIST或HASH分割槽,將建立方式修改為對應的方式即可):
ALTER TABLE
5.5、修改分割槽名稱(修改相關的屬性資訊)
ALTER TABLE TABLE_PARTITION RENAME PARTITION MERGED_PARTITION TO MERGED_PARTITION02;
5.6、交換分割槽(快速交換資料,其實是交換段名稱指標)
首先建立一個交換表,和原表結構相同,如果有資料,必須符合所交換對應分割槽的條件:
CREATE TABLE TABLE_PARTITION_2
AS SELECT * FROM TABLE_PARTITION WHERE 1=2;
然後將第一個分割槽的資料交換出去:
ALTER TABLE TABLE_PARTITION EXCHANGE PARTITION TAB_PARTOTION_01
WITH TABLE TABLE_PARTITION_2 INCLUDING INDEXES;
此時會發現第一個分割槽的資料和表TABLE_PARTITION_2做了瞬間交換,比TRUNCATE還要快,因為這個過程沒有進行資料轉存,只是段名稱的修改過程,和實際的資料量沒有關係。
如果是子分割槽也可以與外部的表進行交換,只需要將關鍵字修改為:SUBPARTITION 即可。
5.7、清空分割槽資料
ALTER TABLE
ALTER TABLE
6、磁碟碎片壓縮
對分割槽表的某分割槽進行磁碟壓縮,當對分割槽內部資料進行了大量的UPDATE、DELETE操作後,一定時間需要進行磁碟壓縮,否則在查詢時,若透過FULL SCAN掃描資料,將會把空塊也會掃描到,對錶進行磁碟壓縮需要進行行遷移操作,所以首先需要操作:
ALTER TABLE
對分割槽表的某分割槽壓縮語法為:
ALTER TABLE
modify partition
對普通表壓縮:
ALTER TABLE
對於索引也需要進行壓縮,索引也是表:
ALTER INDEX
7、分割槽表重新分析以及索引重新分析
對錶進行壓縮後,需要對錶和索引進行重新分析,對錶進行重新分析,一般有兩種方式:
在ORACLE 10G以前,使用:
BEGIN
dbms_stats.gather_table_stats(USER,UPPER('
END;
ORACLE 10G後,可以使用:
ANALYZE TABLE
索引重新分析,將上述兩種方式分別修改一下,如第一種可以使用:gather_index_stats,而第二種修改為:ANALYZE INDEX即可,不過一般比較常用的是重新編譯:
對於分割槽表並進行了索引分割槽的情況,需要對每個分割槽的索引進行重新編譯,這裡以LOCAL索引為例子(其每個索引的分割槽和表分割槽結構相同,預設分割槽名稱和表分割槽名稱相同):
ALTER INDEX
對於全域性索引,根據全域性索引鎖定義的分割槽名稱修改即可,若沒有分割槽,和普通單表索引重新編譯方式相同:
ALTER INDEX
1、關聯物件重新編譯
上述對錶、索引進行重新編譯,尤其對錶進行了壓縮後會產生行遷移,這個過程可能會導致一些檢視、過程物件的失效,此時要將其重新編譯一次。
2、擴充套件:HASH分割槽中,如果建立了新的分割槽,可以將其進行重新HASH分佈:
ALTER TABLE
8、迴歸總結:何時建分割槽,分割槽類別,索引,如何對應SQL
1、建立時機
上述已經說明,2G以上的表,ORACLE推薦建立分割槽。
分割槽的方式根據實際情況而定,才能提高整體效能。
分割槽的欄位一定要是經常用以提取資料的欄位,否則會在提取過程中導致遍歷多個分割槽,這樣比沒有分割槽還要慢。
分割槽欄位要選擇合適,資料較為均勻分佈到各個分割槽,不要太多也不要太少,而且根據分割槽欄位可以很快定位到分割槽範圍。
一般情況下,儘量然業務操作在同一個分割槽內部完成。
2、分割槽類別
分割槽主要有RANGE、LIST、HASH;
RANGE透過值的範圍分割槽,也是最常用的分割槽,這種分割槽注意在一種變長數字字串中,很多人會導致認為是數字型別,而按照數字區分割槽,這樣會分佈十分不均勻的現象發生。
LIST是列舉方式進行分割槽,一般作為二級分割槽而存在(當然也可以自己分割槽,ORACLE 11G後在分割槽上也可以作為主分割槽而存在),在RANGE基礎上,若資料需要繼續分割槽,並且在RANGE基礎上資料量較為固定,只是較大,可以按照一定規則進一步分割槽。
HASH只指定分割槽個數,分割槽細節由ORACLE完成,增加HASH分割槽可以重新分佈資料。
注意:分割槽欄位不能使用函式轉換後在分割槽,如,將某數字字串欄位,先TO_NUMER(COL_NAME)後分割槽。
3、索引類別
大致分:GLOBAL索引和LOCAL索引,錢和可以分:GLOBAL不分割槽索引,和GLOBAL分割槽索引。
GLOBAL不分割槽索引一般不太推薦,因為是用一顆大的索引樹來對映一個表,這個過程,這樣速度不見得比不分割槽快。
GLOBAL分割槽索引,查詢資料若透過要透過索引,是先定位了索引內部的分割槽,然後在這個分割槽索引中找到ROWID,然後回表提取資料。
LOCAL索引是和分割槽的個數逐個對應的,可以說先定位分割槽表的分割槽也可以說先定位索引的分割槽,因為他們是一一對應的,找到對應分割槽後,分割槽內部索引資料集合。
4、對應應用
分割槽表、索引、分割槽索引,要利用其效能優勢,最基本就是要提取資料時,要透過它首先將資料的範圍縮小到一個即使做全盤掃描也不會太慢的情況。
所以SQL一定要有分割槽上的這個欄位的一個WHERE條件,將資料迅速定位到分割槽內部,而且儘量定位到一個分割槽裡面(這個和建立分割槽的規則有關係)。
建立分割槽本身不提要效能,要用好才可提高效能,在必要的RAC叢集中,若存在多分割槽提取資料,適當採用並行提取可以提高提取的速度。
對於索引部分,這裡也只提到分割槽索引的建立方式以及常見索引的維護方式,對於索引原理理解後會更容易認識到提取資料時的技巧。
9、實戰
分割槽表和一般表一樣可以建立索引,分割槽表可以建立區域性索引和全域性索引。當分割槽中出現許多事務並且要保證所有分割槽中的資料記錄的唯一性時採用全域性索引。
1 區域性索引分割槽的建立:
SQL> create index dinya_idx_t on dinya_test(item_id)
2 local
3 (
4 partition idx_1 tablespace dinya_space01,
5 partition idx_2 tablespace dinya_space02,
6 partition idx_3 tablespace dinya_space03
7 );
Index created.
SQL>
看查詢的執行計劃,從下面的執行計劃可以看出,系統已經使用了索引:
SQL> select * from dinya_test partition(part_01) t where t.item_id=12;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=187)
1 0 TABLE ACCESS (BY LOCAL INDEX ROWID) OF 'DINYA_TEST' (Cost=
2 Card=1 Bytes=187)
2 1 INDEX (RANGE SCAN) OF 'DINYA_IDX_T' (NON-UNIQUE) (Cost=1
Card=1)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
334 bytes sent via SQL*Net to client
309 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
2 rows processed
SQL>
2 全域性索引分割槽的建立。
全域性索引建立時global 子句允許指定索引的範圍值,這個範圍值為索引欄位的範圍值:
SQL> create index dinya_idx_t on dinya_test(item_id)
2 global partition by range(item_id)
3 (
4 partition idx_1 values less than (1000) tablespace dinya_space01,
5 partition idx_2 values less than (10000) tablespace dinya_space02,
6 partition idx_3 values less than (maxvalue) tablespace dinya_space03
7 );
Index created.
SQL>
本例中對錶的item_id欄位建立索引分割槽,當然也可以不指定索引分割槽名直接對整個表建立索引,如:
SQL> create index dinya_idx_t on dinya_test(item_id);
Index created.
SQL>
同樣的,對全域性索引根據執行計劃可以看出索引已經可以使用:
SQL> select * from dinya_test t where t.item_id=12;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=3 Bytes=561)
1 0 TABLE ACCESS (BY GLOBAL INDEX ROWID) OF 'DINYA_TEST' (Cost
=2 Card=3 Bytes=561)
2 1 INDEX (RANGE SCAN) OF 'DINYA_IDX_T' (NON-UNIQUE) (Cost=1
Card=3)
Statistics
----------------------------------------------------------
5 recursive calls
0 db block gets
10 consistent gets
0 physical reads
0 redo size
420 bytes sent via SQL*Net to client
309 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
5 rows processed
SQL>
其實分割槽的管理很簡單,難點在於分割槽方式的選擇和分割槽表上面索引的選擇。
Global Index全域性索引和Local Index區域性索引,Global partitioned index和global nonpartitioned index,
選擇多,就越迷惑。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29440247/viewspace-1124295/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深入學習Oracle分割槽表及分割槽索引Oracle索引
- 全面認識oracle分割槽表及分割槽索引Oracle索引
- 分割槽表及分割槽索引建立示例索引
- 簡單ORACLE分割槽表、分割槽索引Oracle索引
- 全面學習分割槽表及分割槽索引(13)--分隔表分割槽索引
- 全面學習分割槽表及分割槽索引(10)--交換分割槽索引
- 全面學習分割槽表及分割槽索引(9)--刪除表分割槽索引
- 全面學習分割槽表及分割槽索引(11)--合併表分割槽索引
- 全面學習分割槽表及分割槽索引(12)--修改list表分割槽索引
- 全面學習分割槽表及分割槽索引(17)--其它索引分割槽管理操作索引
- 全面學習分割槽表及分割槽索引(1)索引
- 深入學習分割槽表及分割槽索引(1)索引
- 全面學習分割槽表及分割槽索引(16)--增加和刪除索引分割槽索引
- oracle分割槽partition及分割槽索引partition index(一)Oracle索引Index
- 全面學習分割槽表及分割槽索引(8)--增加和收縮表分割槽索引
- Oracle分割槽表基礎運維-06分割槽表索引Oracle運維索引
- 全面學習分割槽表及分割槽索引(15)--修改表分割槽屬性和模板索引
- Oracle帶區域性分割槽索引的分割槽表刪除舊分割槽新增新分割槽Oracle索引
- rebuild分割槽表分割槽索引的方法Rebuild索引
- 【學習筆記】分割槽表和分割槽索引——管理索引分割槽(四)筆記索引
- oracle 針對普通表的索引分割槽及10g新增hash 索引分割槽Oracle索引
- 【三思筆記】 全面學習Oracle分割槽表及分割槽索引筆記Oracle索引
- 學習筆記】分割槽表和分割槽索引——新增表分割槽(二)筆記索引
- Oracle索引分割槽Oracle索引
- oracle分割槽表和分割槽表exchangeOracle
- 分割槽表分割槽索引查詢效率探究索引
- 全面學習分割槽表及分割槽索引(6)--建立range-list組合分割槽索引
- 如何查詢分割槽表的分割槽及子分割槽
- 全面學習分割槽表及分割槽索引(7)--怎樣管理索引
- Oracle分割槽表全域性索引新增分割槽時不會失效Oracle索引
- 深入學習分割槽表及分割槽索引(5)--建立range-hash組合分割槽(續)索引
- oracle分割槽表和非分割槽表exchangeOracle
- 分割槽表、分割槽索引和全域性索引部分總結索引
- 【學習筆記】分割槽表和分割槽索引——分割槽表的其他管理(三)筆記索引
- 全面學習分割槽表及分割槽索引(7)--怎樣管理(續)索引
- Oracle分割槽之五:建立分割槽索引總結Oracle索引
- oracle分割槽索引(二)Oracle索引
- oracle分割槽索引(一)Oracle索引