ORACLE分區(qū)表、分區(qū)索引(轉)
ORACLE分區(qū)表、分區(qū)索引ORACLE對于分區(qū)表方式其實就是將表分段存儲,一般普通表格是一個段存儲,而分區(qū)表會分成多個段,所以查找數(shù)據(jù)過程都是先定位根據(jù)查詢條件定位分區(qū)范圍,即數(shù)據(jù)在那個分區(qū)或那幾個內部,然后在分區(qū)內部去查找數(shù)據(jù),一個分區(qū)一般保證四十多萬條數(shù)據(jù)就比較正常了,但是分區(qū)表并非亂建立,而其維護性也相對較為復雜一點,而索引的創(chuàng)建也是有點講究的,這些以下盡量闡述詳細即可。
1、類型說明:
range分區(qū)方式,也算是最常用的分區(qū)方式,其通過某字段或幾個字段的組合的值,從小到大,按照指定的范圍說明進行分區(qū),我們在INSERT數(shù)據(jù)的時候就會存儲到指定的分區(qū)中。
List分區(qū)方式,一般是在range基礎上做的二級分區(qū)較多,是一種列舉方式進行分區(qū),一般講某些地區(qū)、狀態(tài)或指定規(guī)則的編碼等進行劃分。
Hash分區(qū)方式,它沒有固定的規(guī)則,由ORACLE管理,只需要將值INSERT進去,ORACLE會自動去根據(jù)一套HASH算法去劃分分區(qū),只需要告訴ORACLE要分幾個區(qū)即可。
分區(qū)可以進行兩兩組合,ORACLE 11G以前兩兩組合都必須以range作為一級分區(qū)的開頭,ORACLE目前最多支持2級別分區(qū),但這個級別已經(jīng)夠我們使用了。
我這只以最簡單的分區(qū)方式創(chuàng)建分區(qū)來說明問題,就拿range分區(qū)來說明問題吧(基本創(chuàng)建語句如下):
CREATE [url=] TABLE [/url] TABLE_PARTITION(
? ?? ? COL1? ?NUMBER,
? ?? ? COL2? ?VARCHAR2(10)
)?
partition by range(COL1)(
? ?? ?? ? partition TAB_PARTOTION_01 values less than (450000),
? ?? ?? ? partition TAB_PARTOTION_02 values less than (900000),
? ?? ?? ? partition TAB_PARTOTION_03 values less than (1350000),
? ?? ?? ? partition TAB_PARTOTION_04 values less than (1800000),
? ?? ?? ? partition TAB_PARTOTION_OTHER values less THAN (MAXVALUE)
);
這個分區(qū)表創(chuàng)建了四個定長分區(qū),理想情況下,存儲450000條數(shù)據(jù),擴展分區(qū)是超過這個數(shù)額的分區(qū),當發(fā)現(xiàn)擴展分區(qū)有數(shù)據(jù)的時候,可以進行將擴展分區(qū)做SPLIT操作,這個后面說明,這里先說一下一些常用的分區(qū)表查詢功能,我們先插入一些數(shù)據(jù)進去。
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(1,'數(shù)據(jù)測試');
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(23,'數(shù)據(jù)測試');
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(449000,'數(shù)據(jù)測試');
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(450000,'數(shù)據(jù)測試');
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(1350000,'數(shù)據(jù)測試');
INSERT INTO TABLE_PARTITION(COL1,COL2)) ?
VALUES(900000,'數(shù)據(jù)測試');?
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(1800000-1,'數(shù)據(jù)測試');
COMMIT;
為了檢測哪些分區(qū)中有哪些數(shù)據(jù)分別按照分區(qū)去查詢數(shù)據(jù)(應用開發(fā)中基本不會用到,因為不會把分區(qū)寫死)
SQL> SELECT * FROM TABLE_PARTITION partition(TAB_PARTOTION_01);
? ?? ?COL1? ???COL2
---------- ---------------
? ?? ?? ?1? ?? ???數(shù)據(jù)測試
? ?? ???23? ?? ? 數(shù)據(jù)測試
? ? 449000? ? 數(shù)據(jù)測試
說明第一個分區(qū)有:1、23、44900這些數(shù)據(jù),也就是插入時,ORACLE是自己去找分區(qū)的,其實分區(qū)這種子表[url=] 管理 [/url]自己也可以通過程序去完成,ORACLE給你提供了一套,就可以自己去完成了。其余的數(shù)據(jù)就自己查了,都是一個道理。
2、分區(qū)應用:
一般一張表超過2G的大小,ORACLE是推薦使用分區(qū)表的,分區(qū)一般都需要創(chuàng)建索引,說到分區(qū)索引,就可以分為:全局索引、分區(qū)索引,即:global索引和local索引,前者為默認情況下在分區(qū)表上創(chuàng)建索引時的索引方式,并不對索引進行分區(qū)(索引也是表結構,索引大了也需要分區(qū),關于索引以后專門寫點)而全局索引可修飾為分區(qū)索引,但是和local索引有所區(qū)別,前者的分區(qū)方式完全按照自定義方式去創(chuàng)建,和表結構完全無關,所以對于分區(qū)表的全局索引有以下兩幅網(wǎng)上常用的圖解:
2.1、對于分區(qū)表的不分區(qū)索引(這個有點繞,不過就是表分區(qū),但其索引不分區(qū)):
創(chuàng)建語法(直接創(chuàng)建即可):
CREATE INDEX <index_name> ON <partition_table_name>(<column_name>);
2.2、對于分區(qū)表的分區(qū)索引:
創(chuàng)建語法為:
CREATE [url=] INDEX [/url] INX_TAB_PARTITION_COL1 ON TABLE_PARTITION(COL1)
??GLOBAL PARTITION BY RANGE(COL1)
? ?? ?? ?PARTITION IDX_P1 values less than (1000000),
? ?? ?? ?PARTITION IDX_P2 values less than (2000000),
? ?? ?? ?PARTITION IDX_P3 values less than (MAXVALUE)
??)
2.3、LOCAL索引結構:
創(chuàng)建語法為:
CREATE INDEX INX_TAB_PARTITION_COL1 ON TABLE_PARTITION(COL1) LOCAL;
也可按照分區(qū)表的的分區(qū)結構給與一一定義,索引的分區(qū)將得到重命名。
分區(qū)上的位圖索引只能為LOCAL索引,不能為GLOBAL全局索引。
2.4、對比索引方式:
??一般使用LOCAL索引較為方便,而且維護代價較低,并且LOCAL索引是在分區(qū)的基礎上去創(chuàng)建索引,類似于在一個子表內部去創(chuàng)建索引,這樣開銷主要是區(qū)分分區(qū)上,很規(guī)范的管理起來,在OLAP系統(tǒng)中應用很廣泛;而相對的GLOBAL索引是全局類型的索引,根據(jù)實際情況可以調整分區(qū)的類別,而并非按照分區(qū)結構一一定義,相對維護代價較高一些,在OLTP環(huán)境用得相對較多,這里所謂OLTP和OLAP也是相對的,不是特殊的項目,沒有絕對的劃分概念,在應用過程中依據(jù)實際情況而定,來提高整體的運行性能。
3、常用視圖:
1、查詢當前用戶下有哪些是分區(qū)表:
SELECT * FROM USER_PART_TABLES;
2、查詢當前用戶下有哪些分區(qū)索引:
SELECT * FROM USER_PART_INDEXES;
3、查詢當前用戶下分區(qū)索引的分區(qū)信息:
SELECT * FROM USER_IND_PARTITIONS T
WHERE T.INDEX_NAME=?
4、查詢當前用戶下分區(qū)表的分區(qū)信息:
SELECT * FROM USER_TAB_PARTITIONS T
WHERE T.TABLE_NAME=?;
5、查詢某分區(qū)下的數(shù)據(jù)量:
SELECT COUNT(*) FROM TABLE_PARTITION PARTITION(TAB_PARTOTION_01);
6、查詢索引、表上在那些列上創(chuàng)建了分區(qū):
SELECT * FROM USER_PART_KEY_COLUMNS;
7、查詢某用戶下二級分區(qū)的信息(只有創(chuàng)建了二級分區(qū)才有數(shù)據(jù)):
SELECT * FROM USER_TAB_SUBPARTITIONS;
4、維護操作:
4.1、刪除分區(qū)
? ? ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_03;
? ???如果是全局索引,因為全局索引的分區(qū)結構和表可以不一致,若不一致的情況下,會導致整個全局索引失效,在刪除分區(qū)的時候,語句修改為:
? ???ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_03 UPDATE GLOBAL INDEXES;
4.2、分區(qū)合并(從中間刪除掉一個分區(qū),或者兩個分區(qū)需要合并后減少分區(qū)數(shù)量)
? ? 合并分區(qū)和刪除中間的RANGE有點像,但是合并分區(qū)是不會刪除數(shù)據(jù)的,對于LIST、HASH分區(qū)也是和RANGE分區(qū)不一樣的,其語法為:
ALTER TABLE TABLE_PARTITION MERGE PARTITIONS? ? TAB_PARTOTION_01,TAB_PARTOTION_02 INTO PARTITION MERGED_PARTITION;
4.3、分隔分區(qū)(一般分區(qū)從擴展分區(qū)從分隔)
ALTER TABLE TABLE_PARTITION SPLIT PARTITION TAB_PARTOTION_OTHERE AT(2500000)
INTO (PARTITION TAB_PARTOTION_05,PARTITION TAB_PARTOTION_OTHERE);
4.4、創(chuàng)建新的分區(qū)(分區(qū)數(shù)據(jù)若不能提供范圍,則插入時會報錯,需要增加分區(qū)來擴大范圍)
一般有擴展分區(qū)的是都是用分隔的方式,若上述創(chuàng)建表時沒有創(chuàng)建TAB_PARTOTION_OTHER分區(qū)時,在插入數(shù)據(jù)較大時(按照上述建立規(guī)則,超過1800000就應該創(chuàng)建新的分區(qū)來存儲),就可以創(chuàng)建新的分區(qū),如:
為了試驗,我們將擴展分區(qū)先刪除掉再創(chuàng)建新的分區(qū)(因為ORACLE要求,分區(qū)的數(shù)據(jù)不允許重疊,即按照分區(qū)字段同樣的數(shù)據(jù)不能同時存儲在不同的分區(qū)中):
ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_OTHER;
ALTER TABLE TABLE_PARTITION ADD PARTITION TAB_PARTOTION_06 VALUES LESS THAN(2500000);
在分區(qū)下創(chuàng)建新的子分區(qū)大致如下(RANGE分區(qū),若為LIST或HASH分區(qū),將創(chuàng)建方式修改為對應的方式即可):
ALTER TABLE <table_name> MODIFY PARTITION <partition_name> ADD SUBPARTITION <user_define_subpartition_name> VALUES LESS THAN(....);
4.5、修改分區(qū)名稱(修改相關的屬性信息):
ALTER TABLE TABLE_PARTITION RENAME PARTITION MERGED_PARTITION TO MERGED_PARTITION02;
4.6、交換分區(qū)(快速交換數(shù)據(jù),其實是交換段名稱指針)
??首先創(chuàng)建一個交換表,和原表結構相同,如果有數(shù)據(jù),必須符合所交換對應分區(qū)的條件:
CREATE TABLE TABLE_PARTITION_2
??AS SELECT * FROM TABLE_PARTITION WHERE 1=2;
??然后將第一個分區(qū)的數(shù)據(jù)交換出去
ALTER TABLE TABLE_PARTITION EXCHANGE PARTITION TAB_PARTOTION_01
??WITH TABLE TABLE_PARTITION_2 INCLUDING INDEXES;?
??此時會發(fā)現(xiàn)第一個分區(qū)的數(shù)據(jù)和表TABLE_PARTITION_2做了瞬間交換,比TRUNCATE還要快,因為這個過程沒有進行數(shù)據(jù)轉存,只是段名稱的修改過程,和實際的數(shù)據(jù)量沒有關系。
??如果是子分區(qū)也可以與外部的表進行交換,只需要將關鍵字修改為:SUBPARTITION 即可。
4.7、清空分區(qū)數(shù)據(jù)
? ?ALTER TABLE <table_name> TRUNCATE PARTITION <partition_name>;
? ?ALTER TABLE <table_name> TRUNCATE subpartition <subpartition_name>;
9、磁盤碎片壓縮
? ?對分區(qū)表的某分區(qū)進行磁盤壓縮,當對分區(qū)內部數(shù)據(jù)進行了大量的UPDATE、DELETE操作后,一定時間需要進行磁盤壓縮,否則在查詢時,若通過FULL SCAN掃描數(shù)據(jù),將會把空塊也會掃描到,對表進行磁盤壓縮需要進行行遷移操作,所以首先需要操作:
ALTER TABLE <table_name> ENABLE ROW MOVEMENT ;
? ? 對分區(qū)表的某分區(qū)壓縮語法為:
ALTER TABLE <table_name>
modify partition <partition_name> shrink space;
? ?對普通表壓縮:
ALTER TABLE <table_name> shrink space;
??對于索引也需要進行壓縮,索引也是表:
ALTER INDEX <index_name> shrink space;
10、分區(qū)表重新分析以及索引重新分析
??對表進行壓縮后,需要對表和索引進行重新分析,對表進行重新分析,一般有兩種方式:
??在ORACLE 10G以前,使用:
BEGIN
? ???dbms_stats.gather_table_stats(USER,UPPER('<table_name>'));
??END;
??ORACLE 10G后,可以使用:
??ANALYZE TABLE <table_name> COMPUTE STATISTICS;
??索引重新分析,將上述兩種方式分別修改一下,如第一種可以使用:gather_index_stats,而第二種修改為:ANALYZE INDEX即可,不過一般比較常用的是重新編譯:
??對于分區(qū)表并進行了索引分區(qū)的情況,需要對每個分區(qū)的索引進行重新編譯,這里以LOCAL索引為例子(其每個索引的分區(qū)和表分區(qū)結構相同,默認分區(qū)名稱和表分區(qū)名稱相同):
ALTER INDEX <index_name> REBUILD PARTITION <partition_name>;
??對于全局索引,根據(jù)全局索引鎖定義的分區(qū)名稱修改即可,若沒有分區(qū),和普通單表索引重新編譯方式相同:
ALTER INDEX <index_name> REBUILD;
11、關聯(lián)對象重新編譯,
??上述對表、索引進行重新編譯,尤其對表進行了壓縮后會產生行遷移,這個過程可能會導致一些視圖、過程對象的失效,此時要將其重新編譯一次。
12、擴展:HASH分區(qū)中,如果創(chuàng)建了新的分區(qū),可以將其進行重新HASH分布:
ALTER TABLE <table_name> COALESCA PARTITION% ?
5、回歸總結:何時建分區(qū),分區(qū)類別,索引,如何對應[url=] SQL [/url]
1、創(chuàng)建時機
? ???上述已經(jīng)說明,2G以上的表,ORACLE推薦創(chuàng)建分區(qū)。
? ???分區(qū)的方式根據(jù)實際情況而定,才能提高整體性能。
? ???分區(qū)的字段一定要是經(jīng)常用以提取數(shù)據(jù)的字段,否則會在提取過程中導致遍歷多個分區(qū),這樣比沒有分區(qū)還要慢。
? ???分區(qū)字段要選擇合適,數(shù)據(jù)較為均勻分布到各個分區(qū),不要太多也不要太少,而且根據(jù)分區(qū)字段可以很快定位到分區(qū)范圍。
? ???一般情況下,盡量然業(yè)務操作在同一個分區(qū)內部完成。
2、分區(qū)類別
? ? 分區(qū)主要有RANGE、LIST、HASH;
? ???RANGE通過值的范圍分區(qū),也是最常用的分區(qū),這種分區(qū)注意在一種變長數(shù)字字符串中,很多人會導致認為是數(shù)字類型,而按照數(shù)字區(qū)分區(qū),這樣會分布十分不均勻的現(xiàn)象發(fā)生。
? ???LIST是列舉方式進行分區(qū),一般作為二級分區(qū)而存在(當然也可以自己分區(qū),ORACLE 11G后在分區(qū)上也可以作為主分區(qū)而存在),在RANGE基礎上,若數(shù)據(jù)需要繼續(xù)分區(qū),并且在RANGE基礎上數(shù)據(jù)量較為固定,只是較大,可以按照一定規(guī)則進一步分區(qū)。??}?
? ???HASH只指定分區(qū)個數(shù),分區(qū)細節(jié)由ORACLE完成,增加HASH分區(qū)可以重新分布數(shù)據(jù)。
? ? 大致分:GLOBAL索引和LOCAL索引,錢和可以分:GLOBAL不分區(qū)索引,和GLOBAL分區(qū)索引。
? ???GLOBAL不分區(qū)索引一般不太推薦,因為是用一顆大的索引樹來映射一個表,這個過程,這樣速度不見得比不分區(qū)快。
? ???GLOBAL分區(qū)索引,查找數(shù)據(jù)若通過要通過索引,是先定位了索引內部的分區(qū),然后在這個分區(qū)索引中找到ROWID,然后回表提取數(shù)據(jù)。
? ???LOCAL索引是和分區(qū)的個數(shù)逐個對應的,可以說先定位分區(qū)表的分區(qū)也可以說先定位索引的分區(qū),因為他們是一一對應的,找到對應分區(qū)后,分區(qū)內部索引數(shù)據(jù)集合。
4、對應應用0?
? ???分區(qū)表、索引、分區(qū)索引,要利用其性能優(yōu)勢,最基本就是要提取數(shù)據(jù)時,要通過它首先將數(shù)據(jù)的范圍縮小到一個即使做全盤掃描也不會太慢的情況。
? ?? ?所以SQL一定要有分區(qū)上的這個字段的一個WHERE條件,將數(shù)據(jù)迅速定位到分區(qū)內部,而且盡量定位到一個分區(qū)里面(這個和創(chuàng)建分區(qū)的規(guī)則有關系)。
? ?? ?建立分區(qū)本身不提要性能,要用好才可提高性能,在必要的RAC集群中,若存在多分區(qū)提取數(shù)據(jù),適當采用并行提取可以提高提取的速度。
? ?? ?對于索引部分,這里也只提到分區(qū)索引的創(chuàng)建方式以及常見索引的維護方式,對于索引原理理解后會更容易認識到提取數(shù)據(jù)時的技巧。
1、類型說明:
range分區(qū)方式,也算是最常用的分區(qū)方式,其通過某字段或幾個字段的組合的值,從小到大,按照指定的范圍說明進行分區(qū),我們在INSERT數(shù)據(jù)的時候就會存儲到指定的分區(qū)中。
List分區(qū)方式,一般是在range基礎上做的二級分區(qū)較多,是一種列舉方式進行分區(qū),一般講某些地區(qū)、狀態(tài)或指定規(guī)則的編碼等進行劃分。
Hash分區(qū)方式,它沒有固定的規(guī)則,由ORACLE管理,只需要將值INSERT進去,ORACLE會自動去根據(jù)一套HASH算法去劃分分區(qū),只需要告訴ORACLE要分幾個區(qū)即可。
分區(qū)可以進行兩兩組合,ORACLE 11G以前兩兩組合都必須以range作為一級分區(qū)的開頭,ORACLE目前最多支持2級別分區(qū),但這個級別已經(jīng)夠我們使用了。
我這只以最簡單的分區(qū)方式創(chuàng)建分區(qū)來說明問題,就拿range分區(qū)來說明問題吧(基本創(chuàng)建語句如下):
CREATE [url=] TABLE [/url] TABLE_PARTITION(
? ?? ? COL1? ?NUMBER,
? ?? ? COL2? ?VARCHAR2(10)
)?
partition by range(COL1)(
? ?? ?? ? partition TAB_PARTOTION_01 values less than (450000),
? ?? ?? ? partition TAB_PARTOTION_02 values less than (900000),
? ?? ?? ? partition TAB_PARTOTION_03 values less than (1350000),
? ?? ?? ? partition TAB_PARTOTION_04 values less than (1800000),
? ?? ?? ? partition TAB_PARTOTION_OTHER values less THAN (MAXVALUE)
);
這個分區(qū)表創(chuàng)建了四個定長分區(qū),理想情況下,存儲450000條數(shù)據(jù),擴展分區(qū)是超過這個數(shù)額的分區(qū),當發(fā)現(xiàn)擴展分區(qū)有數(shù)據(jù)的時候,可以進行將擴展分區(qū)做SPLIT操作,這個后面說明,這里先說一下一些常用的分區(qū)表查詢功能,我們先插入一些數(shù)據(jù)進去。
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(1,'數(shù)據(jù)測試');
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(23,'數(shù)據(jù)測試');
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(449000,'數(shù)據(jù)測試');
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(450000,'數(shù)據(jù)測試');
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(1350000,'數(shù)據(jù)測試');
INSERT INTO TABLE_PARTITION(COL1,COL2)) ?
VALUES(900000,'數(shù)據(jù)測試');?
INSERT INTO TABLE_PARTITION(COL1,COL2)
VALUES(1800000-1,'數(shù)據(jù)測試');
COMMIT;
為了檢測哪些分區(qū)中有哪些數(shù)據(jù)分別按照分區(qū)去查詢數(shù)據(jù)(應用開發(fā)中基本不會用到,因為不會把分區(qū)寫死)
SQL> SELECT * FROM TABLE_PARTITION partition(TAB_PARTOTION_01);
? ?? ?COL1? ???COL2
---------- ---------------
? ?? ?? ?1? ?? ???數(shù)據(jù)測試
? ?? ???23? ?? ? 數(shù)據(jù)測試
? ? 449000? ? 數(shù)據(jù)測試
說明第一個分區(qū)有:1、23、44900這些數(shù)據(jù),也就是插入時,ORACLE是自己去找分區(qū)的,其實分區(qū)這種子表[url=] 管理 [/url]自己也可以通過程序去完成,ORACLE給你提供了一套,就可以自己去完成了。其余的數(shù)據(jù)就自己查了,都是一個道理。
2、分區(qū)應用:
一般一張表超過2G的大小,ORACLE是推薦使用分區(qū)表的,分區(qū)一般都需要創(chuàng)建索引,說到分區(qū)索引,就可以分為:全局索引、分區(qū)索引,即:global索引和local索引,前者為默認情況下在分區(qū)表上創(chuàng)建索引時的索引方式,并不對索引進行分區(qū)(索引也是表結構,索引大了也需要分區(qū),關于索引以后專門寫點)而全局索引可修飾為分區(qū)索引,但是和local索引有所區(qū)別,前者的分區(qū)方式完全按照自定義方式去創(chuàng)建,和表結構完全無關,所以對于分區(qū)表的全局索引有以下兩幅網(wǎng)上常用的圖解:
2.1、對于分區(qū)表的不分區(qū)索引(這個有點繞,不過就是表分區(qū),但其索引不分區(qū)):

創(chuàng)建語法(直接創(chuàng)建即可):
CREATE INDEX <index_name> ON <partition_table_name>(<column_name>);
2.2、對于分區(qū)表的分區(qū)索引:

創(chuàng)建語法為:
CREATE [url=] INDEX [/url] INX_TAB_PARTITION_COL1 ON TABLE_PARTITION(COL1)
??GLOBAL PARTITION BY RANGE(COL1)
? ?? ?? ?PARTITION IDX_P1 values less than (1000000),
? ?? ?? ?PARTITION IDX_P2 values less than (2000000),
? ?? ?? ?PARTITION IDX_P3 values less than (MAXVALUE)
??)
2.3、LOCAL索引結構:

創(chuàng)建語法為:
CREATE INDEX INX_TAB_PARTITION_COL1 ON TABLE_PARTITION(COL1) LOCAL;
也可按照分區(qū)表的的分區(qū)結構給與一一定義,索引的分區(qū)將得到重命名。
分區(qū)上的位圖索引只能為LOCAL索引,不能為GLOBAL全局索引。
2.4、對比索引方式:
??一般使用LOCAL索引較為方便,而且維護代價較低,并且LOCAL索引是在分區(qū)的基礎上去創(chuàng)建索引,類似于在一個子表內部去創(chuàng)建索引,這樣開銷主要是區(qū)分分區(qū)上,很規(guī)范的管理起來,在OLAP系統(tǒng)中應用很廣泛;而相對的GLOBAL索引是全局類型的索引,根據(jù)實際情況可以調整分區(qū)的類別,而并非按照分區(qū)結構一一定義,相對維護代價較高一些,在OLTP環(huán)境用得相對較多,這里所謂OLTP和OLAP也是相對的,不是特殊的項目,沒有絕對的劃分概念,在應用過程中依據(jù)實際情況而定,來提高整體的運行性能。
3、常用視圖:
1、查詢當前用戶下有哪些是分區(qū)表:
SELECT * FROM USER_PART_TABLES;
2、查詢當前用戶下有哪些分區(qū)索引:
SELECT * FROM USER_PART_INDEXES;
3、查詢當前用戶下分區(qū)索引的分區(qū)信息:
SELECT * FROM USER_IND_PARTITIONS T
WHERE T.INDEX_NAME=?
4、查詢當前用戶下分區(qū)表的分區(qū)信息:
SELECT * FROM USER_TAB_PARTITIONS T
WHERE T.TABLE_NAME=?;
5、查詢某分區(qū)下的數(shù)據(jù)量:
SELECT COUNT(*) FROM TABLE_PARTITION PARTITION(TAB_PARTOTION_01);
6、查詢索引、表上在那些列上創(chuàng)建了分區(qū):
SELECT * FROM USER_PART_KEY_COLUMNS;
7、查詢某用戶下二級分區(qū)的信息(只有創(chuàng)建了二級分區(qū)才有數(shù)據(jù)):
SELECT * FROM USER_TAB_SUBPARTITIONS;
4、維護操作:
4.1、刪除分區(qū)
? ? ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_03;
? ???如果是全局索引,因為全局索引的分區(qū)結構和表可以不一致,若不一致的情況下,會導致整個全局索引失效,在刪除分區(qū)的時候,語句修改為:
? ???ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_03 UPDATE GLOBAL INDEXES;
4.2、分區(qū)合并(從中間刪除掉一個分區(qū),或者兩個分區(qū)需要合并后減少分區(qū)數(shù)量)
? ? 合并分區(qū)和刪除中間的RANGE有點像,但是合并分區(qū)是不會刪除數(shù)據(jù)的,對于LIST、HASH分區(qū)也是和RANGE分區(qū)不一樣的,其語法為:
ALTER TABLE TABLE_PARTITION MERGE PARTITIONS? ? TAB_PARTOTION_01,TAB_PARTOTION_02 INTO PARTITION MERGED_PARTITION;
4.3、分隔分區(qū)(一般分區(qū)從擴展分區(qū)從分隔)
ALTER TABLE TABLE_PARTITION SPLIT PARTITION TAB_PARTOTION_OTHERE AT(2500000)
INTO (PARTITION TAB_PARTOTION_05,PARTITION TAB_PARTOTION_OTHERE);
4.4、創(chuàng)建新的分區(qū)(分區(qū)數(shù)據(jù)若不能提供范圍,則插入時會報錯,需要增加分區(qū)來擴大范圍)
一般有擴展分區(qū)的是都是用分隔的方式,若上述創(chuàng)建表時沒有創(chuàng)建TAB_PARTOTION_OTHER分區(qū)時,在插入數(shù)據(jù)較大時(按照上述建立規(guī)則,超過1800000就應該創(chuàng)建新的分區(qū)來存儲),就可以創(chuàng)建新的分區(qū),如:
為了試驗,我們將擴展分區(qū)先刪除掉再創(chuàng)建新的分區(qū)(因為ORACLE要求,分區(qū)的數(shù)據(jù)不允許重疊,即按照分區(qū)字段同樣的數(shù)據(jù)不能同時存儲在不同的分區(qū)中):
ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_OTHER;
ALTER TABLE TABLE_PARTITION ADD PARTITION TAB_PARTOTION_06 VALUES LESS THAN(2500000);
在分區(qū)下創(chuàng)建新的子分區(qū)大致如下(RANGE分區(qū),若為LIST或HASH分區(qū),將創(chuàng)建方式修改為對應的方式即可):
ALTER TABLE <table_name> MODIFY PARTITION <partition_name> ADD SUBPARTITION <user_define_subpartition_name> VALUES LESS THAN(....);
4.5、修改分區(qū)名稱(修改相關的屬性信息):
ALTER TABLE TABLE_PARTITION RENAME PARTITION MERGED_PARTITION TO MERGED_PARTITION02;
4.6、交換分區(qū)(快速交換數(shù)據(jù),其實是交換段名稱指針)
??首先創(chuàng)建一個交換表,和原表結構相同,如果有數(shù)據(jù),必須符合所交換對應分區(qū)的條件:
CREATE TABLE TABLE_PARTITION_2
??AS SELECT * FROM TABLE_PARTITION WHERE 1=2;
??然后將第一個分區(qū)的數(shù)據(jù)交換出去
ALTER TABLE TABLE_PARTITION EXCHANGE PARTITION TAB_PARTOTION_01
??WITH TABLE TABLE_PARTITION_2 INCLUDING INDEXES;?
??此時會發(fā)現(xiàn)第一個分區(qū)的數(shù)據(jù)和表TABLE_PARTITION_2做了瞬間交換,比TRUNCATE還要快,因為這個過程沒有進行數(shù)據(jù)轉存,只是段名稱的修改過程,和實際的數(shù)據(jù)量沒有關系。
??如果是子分區(qū)也可以與外部的表進行交換,只需要將關鍵字修改為:SUBPARTITION 即可。
4.7、清空分區(qū)數(shù)據(jù)
? ?ALTER TABLE <table_name> TRUNCATE PARTITION <partition_name>;
? ?ALTER TABLE <table_name> TRUNCATE subpartition <subpartition_name>;
9、磁盤碎片壓縮
? ?對分區(qū)表的某分區(qū)進行磁盤壓縮,當對分區(qū)內部數(shù)據(jù)進行了大量的UPDATE、DELETE操作后,一定時間需要進行磁盤壓縮,否則在查詢時,若通過FULL SCAN掃描數(shù)據(jù),將會把空塊也會掃描到,對表進行磁盤壓縮需要進行行遷移操作,所以首先需要操作:
ALTER TABLE <table_name> ENABLE ROW MOVEMENT ;
? ? 對分區(qū)表的某分區(qū)壓縮語法為:
ALTER TABLE <table_name>
modify partition <partition_name> shrink space;
? ?對普通表壓縮:
ALTER TABLE <table_name> shrink space;
??對于索引也需要進行壓縮,索引也是表:
ALTER INDEX <index_name> shrink space;
10、分區(qū)表重新分析以及索引重新分析
??對表進行壓縮后,需要對表和索引進行重新分析,對表進行重新分析,一般有兩種方式:
??在ORACLE 10G以前,使用:
BEGIN
? ???dbms_stats.gather_table_stats(USER,UPPER('<table_name>'));
??END;
??ORACLE 10G后,可以使用:
??ANALYZE TABLE <table_name> COMPUTE STATISTICS;
??索引重新分析,將上述兩種方式分別修改一下,如第一種可以使用:gather_index_stats,而第二種修改為:ANALYZE INDEX即可,不過一般比較常用的是重新編譯:
??對于分區(qū)表并進行了索引分區(qū)的情況,需要對每個分區(qū)的索引進行重新編譯,這里以LOCAL索引為例子(其每個索引的分區(qū)和表分區(qū)結構相同,默認分區(qū)名稱和表分區(qū)名稱相同):
ALTER INDEX <index_name> REBUILD PARTITION <partition_name>;
??對于全局索引,根據(jù)全局索引鎖定義的分區(qū)名稱修改即可,若沒有分區(qū),和普通單表索引重新編譯方式相同:
ALTER INDEX <index_name> REBUILD;
11、關聯(lián)對象重新編譯,
??上述對表、索引進行重新編譯,尤其對表進行了壓縮后會產生行遷移,這個過程可能會導致一些視圖、過程對象的失效,此時要將其重新編譯一次。
12、擴展:HASH分區(qū)中,如果創(chuàng)建了新的分區(qū),可以將其進行重新HASH分布:
ALTER TABLE <table_name> COALESCA PARTITION% ?
5、回歸總結:何時建分區(qū),分區(qū)類別,索引,如何對應[url=] SQL [/url]
1、創(chuàng)建時機
? ???上述已經(jīng)說明,2G以上的表,ORACLE推薦創(chuàng)建分區(qū)。
? ???分區(qū)的方式根據(jù)實際情況而定,才能提高整體性能。
? ???分區(qū)的字段一定要是經(jīng)常用以提取數(shù)據(jù)的字段,否則會在提取過程中導致遍歷多個分區(qū),這樣比沒有分區(qū)還要慢。
? ???分區(qū)字段要選擇合適,數(shù)據(jù)較為均勻分布到各個分區(qū),不要太多也不要太少,而且根據(jù)分區(qū)字段可以很快定位到分區(qū)范圍。
? ???一般情況下,盡量然業(yè)務操作在同一個分區(qū)內部完成。
2、分區(qū)類別
? ? 分區(qū)主要有RANGE、LIST、HASH;
? ???RANGE通過值的范圍分區(qū),也是最常用的分區(qū),這種分區(qū)注意在一種變長數(shù)字字符串中,很多人會導致認為是數(shù)字類型,而按照數(shù)字區(qū)分區(qū),這樣會分布十分不均勻的現(xiàn)象發(fā)生。
? ???LIST是列舉方式進行分區(qū),一般作為二級分區(qū)而存在(當然也可以自己分區(qū),ORACLE 11G后在分區(qū)上也可以作為主分區(qū)而存在),在RANGE基礎上,若數(shù)據(jù)需要繼續(xù)分區(qū),并且在RANGE基礎上數(shù)據(jù)量較為固定,只是較大,可以按照一定規(guī)則進一步分區(qū)。??}?
? ???HASH只指定分區(qū)個數(shù),分區(qū)細節(jié)由ORACLE完成,增加HASH分區(qū)可以重新分布數(shù)據(jù)。
? ???注意:分區(qū)字段不能使用函數(shù)轉換后在分區(qū),如,將某數(shù)字字符串字段,先TO_NUMER(COL_NAME)后分區(qū)。
?
3、索引類別? ? 大致分:GLOBAL索引和LOCAL索引,錢和可以分:GLOBAL不分區(qū)索引,和GLOBAL分區(qū)索引。
? ???GLOBAL不分區(qū)索引一般不太推薦,因為是用一顆大的索引樹來映射一個表,這個過程,這樣速度不見得比不分區(qū)快。
? ???GLOBAL分區(qū)索引,查找數(shù)據(jù)若通過要通過索引,是先定位了索引內部的分區(qū),然后在這個分區(qū)索引中找到ROWID,然后回表提取數(shù)據(jù)。
? ???LOCAL索引是和分區(qū)的個數(shù)逐個對應的,可以說先定位分區(qū)表的分區(qū)也可以說先定位索引的分區(qū),因為他們是一一對應的,找到對應分區(qū)后,分區(qū)內部索引數(shù)據(jù)集合。
4、對應應用0?
? ???分區(qū)表、索引、分區(qū)索引,要利用其性能優(yōu)勢,最基本就是要提取數(shù)據(jù)時,要通過它首先將數(shù)據(jù)的范圍縮小到一個即使做全盤掃描也不會太慢的情況。
? ?? ?所以SQL一定要有分區(qū)上的這個字段的一個WHERE條件,將數(shù)據(jù)迅速定位到分區(qū)內部,而且盡量定位到一個分區(qū)里面(這個和創(chuàng)建分區(qū)的規(guī)則有關系)。
? ?? ?建立分區(qū)本身不提要性能,要用好才可提高性能,在必要的RAC集群中,若存在多分區(qū)提取數(shù)據(jù),適當采用并行提取可以提高提取的速度。
? ?? ?對于索引部分,這里也只提到分區(qū)索引的創(chuàng)建方式以及常見索引的維護方式,對于索引原理理解后會更容易認識到提取數(shù)據(jù)時的技巧。
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
