ORACLE HANDBOOK系列之十一:分区(Partition)
Partitioning enables you to decompose very large tables and indexes into smaller and more manageable pieces called partitions. Each partition is an independent object with its own name and optionally its own storage characteristics.
Oracle允許用戶將大表以及大的索引拆分成小塊,每一塊都是一個(gè)單獨(dú)的對(duì)象,稱為分區(qū),分區(qū)技術(shù)可以用于提高查詢及DML性能、以及更便捷地管理數(shù)據(jù)。
?
1. ?分區(qū)表
1.1. ?分區(qū)表主要包括三種:
Range Partitioning
List Partitioning
Hash partitioning
?
1.2.?分區(qū)表創(chuàng)建語法示例(Range分區(qū)):
CREATE TABLE tab_part_0309(val DATE, val2 VARCHAR2(200))PARTITION BY RANGE(val)
(
PARTITION p1 VALUES LESS THAN (TO_DATE('20120308','yyyymmdd'))
);
?
1.3.?ORA-14400錯(cuò)誤
如果在插入數(shù)據(jù)時(shí)Oracle無法找到合適的分區(qū),就會(huì)產(chǎn)生ORA-14400錯(cuò)誤,”inserted partition key does not map to any partition”。例如(假設(shè)當(dāng)前為2012-03-09):
INSERT INTO tab_part_0309 VALUES(SYSDATE,'abrownfox');?
1.4.?如何添加分區(qū)
ALTER TABLE tab_part_0309 ADD PARTITION p2 VALUES LESS THAN (TO_DATE('20120309','yyyymmdd'));ALTER TABLE tab_part_0309 ADD PARTITION p3 VALUES LESS THAN (TO_DATE('20120310','yyyymmdd'));
?
1.5.?查詢
SELECT * FROM tab_part_0309 PARTITION(p3);查詢時(shí)我們可以指定分區(qū)。不過更常見的是Oracle自動(dòng)的Partition Pruning,即如果查詢時(shí)Where子句中包括用于分區(qū)的列(示例中的val列),Oracle會(huì)自動(dòng)定位分區(qū),而不用我們手工指定分區(qū)。
?
1.6.?刪除分區(qū)
ALTER TABLE tab_part_0309 DROP PARTITION p3;?
1.7.?MAXVALUE
一些情況下,我們會(huì)通過定時(shí)任務(wù)(Scheduler)來定期創(chuàng)建分區(qū),這時(shí)候我們需要考慮一個(gè)問題,如果定時(shí)任務(wù)失敗了導(dǎo)致分區(qū)沒有建立, 那么后斯的數(shù)據(jù)插入就會(huì)遇到ORA-14400錯(cuò)誤。有一種方法可以避免這種錯(cuò)誤,使用MAXVALUE:
CREATE TABLE tab_part_0309_2(val DATE, val2 VARCHAR2(200))PARTITION BY RANGE(val)
(
PARTITION p1 VALUES LESS THAN (TO_DATE('20120308','yyyymmdd')),
PARTITION pm VALUES LESS THAN (MAXVALUE)
);
使用MAXVALUE后,無法再添加新的分區(qū):
ALTER TABLE tab_part_0309_2 ADD PARTITION p2 VALUES LESS THAN (TO_DATE('20120310','yyyymmdd'))ORA-14074, partition bound must be collate higher than that of the last partition
但是我們可以從pm分區(qū)中進(jìn)行拆分:
ALTER TABLE tab_part_0309_2SPLIT PARTITION pm AT (TO_DATE('20120310','yyyymmdd'))
INTO (PARTITION p2, PARTITION pm)
這樣的好處是,即便執(zhí)行拆分的定時(shí)任務(wù)失敗了,數(shù)據(jù)仍然可以正常插入(只不過進(jìn)入了pm分區(qū))。同時(shí),發(fā)現(xiàn)錯(cuò)誤后,我們可以進(jìn)行補(bǔ)救,手工拆分出一個(gè)分區(qū),這樣,pm中符合新分區(qū)條件的數(shù)據(jù),會(huì)自動(dòng)進(jìn)行新的分區(qū)。
?
1.8.?Interval partitioning
11G中引入了一個(gè)更為強(qiáng)大的分區(qū)機(jī)制:Interval partitioning,可以按一定條件自動(dòng)創(chuàng)建分區(qū)。創(chuàng)建語法是這樣的:
CREATE TABLE tab_part_0309_3(val DATE, val2 VARCHAR2(200))PARTITION BY RANGE(val)
INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION p1 VALUES LESS THAN (TO_DATE('20120308','yyyymmdd'))
);
Interval分區(qū)表必須指定一個(gè)根分區(qū)(上例的p1),使用Interval指定分區(qū)的間隔,它使用了NumToYMInterval函數(shù),該函數(shù)第一個(gè)參數(shù)是number,后一個(gè)是單位,包括’MONTH’, ‘YEAR’,上例表示間隔為一個(gè)月,目前看一個(gè)月應(yīng)該是最小的間隔了,你可以指定0.5或者0.3,但最終的效果還是一個(gè)月。
假設(shè)當(dāng)前時(shí)間為2012-03-09,執(zhí)行下述語句
INSERT INTO tab_part_0309_3 VALUES(SYSDATE, 'abrownfox');1)???????????? 導(dǎo)致自動(dòng)創(chuàng)建新分區(qū)
2)???????????? 分區(qū)字段值為2012-04-08,是從根分區(qū)往后的一個(gè)月時(shí)間。
3)???????????? 分區(qū)名稱自動(dòng)生成,如SYS_P21
4)???????????? 如果插入的時(shí)間在兩個(gè)月以后或者更久,則Oracle只生成必須的分區(qū),并不會(huì)生成連續(xù)分區(qū)。例如insert的時(shí)間是2012-06-01,則只會(huì)生成2012-06-08分區(qū),至于中間的2012-05-08,2012-04-08分區(qū)并不生成。
?
2.?分區(qū)索引
跟表一樣,索引也分為普通索引與文藝索引(就當(dāng)分區(qū)索引比較文藝一點(diǎn)吧)。可以為一張普通表創(chuàng)建分區(qū)索引(不過不能創(chuàng)建Local分區(qū)索引,后面解釋),也可以為一張分區(qū)表創(chuàng)建普通索引。
2.1.?分區(qū)索引分兩類
全局分區(qū)索引(global partitioning index)
本地分區(qū)索引(local partitioning index)
?
2.2.?全局分區(qū)索引
與表的分區(qū)沒有關(guān)系,創(chuàng)建索引時(shí)可以指定任意的列作為索引分區(qū)的Key,創(chuàng)建語法如下:
CREATE TABLE tab_part_0321_2(val DATE, val2 NUMBER)PARTITION BY RANGE(val)
(
PARTITION p1 VALUES LESS THAN (TO_DATE('20120308','yyyymmdd'))
);
CREATE INDEX tab_part_0321_2_idx ON tab_part_0321_2 (val2)
GLOBAL PARTITION BY RANGE (val2)
(PARTITION p1 VALUES LESS THAN (2),
PARTITION p2 VALUES LESS THAN (3),
PARTITION p3 VALUES LESS THAN (MAXVALUE));
注意這里使用了global關(guān)鍵字, 并且索引分區(qū)使用的Key是val2字段,而不是表分區(qū)使用的val字段。
那么是否可以在為字段val2創(chuàng)建索引但是使用val字段作為分區(qū)的key呢?
CREATE INDEX tab_part_0321_2_idx2 ON tab_part_0321_2 (val2)GLOBAL PARTITION BY RANGE (val)
(PARTITION pa VALUES LESS THAN (to_date('20120308','yyyymmdd')),
PARTITION pb VALUES LESS THAN (to_date('20120408','yyyymmdd')),
PARTITION pc VALUES LESS THAN (MAXVALUE));
ORA-14038 global partitioned index must be prefixed.
Prefixed即“前綴索引”,指索引鍵與分區(qū)鍵是相同的,Oracle無法創(chuàng)建非前綴的全局分區(qū)索引。
?
2.3.?本地分區(qū)索引
只有分區(qū)表才能創(chuàng)建本地分區(qū)索引,本地分區(qū)索引始終使用與分區(qū)表相同的字段進(jìn)行分區(qū)(不需要partition by子句),因此索引的分區(qū)與表的分區(qū)是一一對(duì)應(yīng)的。我們看看語法:
CREATE INDEX tab_part_0321_2_idx3 ON tab_part_0321_2 (val) LOCAL嘗試:
CREATE INDEX tab_part_0321_2_idx4 ON tab_part_0321_2 (val2) LOCALORA-01408 such column list already indexed
這是因?yàn)樵谇耙恍」?jié)我們?cè)谶@個(gè)列上創(chuàng)建過索引了,我們回去把tab_part_0321_2_idx移除,重新執(zhí)行上面的語句便可創(chuàng)建成功,這說明跟global分區(qū)索引不同,local分區(qū)索引允許創(chuàng)建“非前綴索引”。
?
注:關(guān)于前面提到的本地前綴索引(local prefixed index)與本地非前綴索引(local non-prefixed index)的概念,有興趣的可以看看OTN的一些討論帖子,比如:https://forums.oracle.com/forums/thread.jspa?threadID=2150455&start=0&tstart=0
??
轉(zhuǎn)載于:https://www.cnblogs.com/morvenhuang/archive/2012/03/22/2411861.html
總結(jié)
以上是生活随笔為你收集整理的ORACLE HANDBOOK系列之十一:分区(Partition)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL Server 2005中的分区表
- 下一篇: 华为eudemon 200E的hrp双心