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允許用戶將大表以及大的索引拆分成小塊,每一塊都是一個單獨的對象,稱為分區,分區技術可以用于提高查詢及DML性能、以及更便捷地管理數據。
?
1. ?分區表
1.1. ?分區表主要包括三種:
Range Partitioning
List Partitioning
Hash partitioning
?
1.2.?分區表創建語法示例(Range分區):
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錯誤
如果在插入數據時Oracle無法找到合適的分區,就會產生ORA-14400錯誤,”inserted partition key does not map to any partition”。例如(假設當前為2012-03-09):
INSERT INTO tab_part_0309 VALUES(SYSDATE,'abrownfox');?
1.4.?如何添加分區
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);查詢時我們可以指定分區。不過更常見的是Oracle自動的Partition Pruning,即如果查詢時Where子句中包括用于分區的列(示例中的val列),Oracle會自動定位分區,而不用我們手工指定分區。
?
1.6.?刪除分區
ALTER TABLE tab_part_0309 DROP PARTITION p3;?
1.7.?MAXVALUE
一些情況下,我們會通過定時任務(Scheduler)來定期創建分區,這時候我們需要考慮一個問題,如果定時任務失敗了導致分區沒有建立, 那么后斯的數據插入就會遇到ORA-14400錯誤。有一種方法可以避免這種錯誤,使用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后,無法再添加新的分區:
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分區中進行拆分:
ALTER TABLE tab_part_0309_2SPLIT PARTITION pm AT (TO_DATE('20120310','yyyymmdd'))
INTO (PARTITION p2, PARTITION pm)
這樣的好處是,即便執行拆分的定時任務失敗了,數據仍然可以正常插入(只不過進入了pm分區)。同時,發現錯誤后,我們可以進行補救,手工拆分出一個分區,這樣,pm中符合新分區條件的數據,會自動進行新的分區。
?
1.8.?Interval partitioning
11G中引入了一個更為強大的分區機制:Interval partitioning,可以按一定條件自動創建分區。創建語法是這樣的:
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分區表必須指定一個根分區(上例的p1),使用Interval指定分區的間隔,它使用了NumToYMInterval函數,該函數第一個參數是number,后一個是單位,包括’MONTH’, ‘YEAR’,上例表示間隔為一個月,目前看一個月應該是最小的間隔了,你可以指定0.5或者0.3,但最終的效果還是一個月。
假設當前時間為2012-03-09,執行下述語句
INSERT INTO tab_part_0309_3 VALUES(SYSDATE, 'abrownfox');1)???????????? 導致自動創建新分區
2)???????????? 分區字段值為2012-04-08,是從根分區往后的一個月時間。
3)???????????? 分區名稱自動生成,如SYS_P21
4)???????????? 如果插入的時間在兩個月以后或者更久,則Oracle只生成必須的分區,并不會生成連續分區。例如insert的時間是2012-06-01,則只會生成2012-06-08分區,至于中間的2012-05-08,2012-04-08分區并不生成。
?
2.?分區索引
跟表一樣,索引也分為普通索引與文藝索引(就當分區索引比較文藝一點吧)。可以為一張普通表創建分區索引(不過不能創建Local分區索引,后面解釋),也可以為一張分區表創建普通索引。
2.1.?分區索引分兩類
全局分區索引(global partitioning index)
本地分區索引(local partitioning index)
?
2.2.?全局分區索引
與表的分區沒有關系,創建索引時可以指定任意的列作為索引分區的Key,創建語法如下:
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關鍵字, 并且索引分區使用的Key是val2字段,而不是表分區使用的val字段。
那么是否可以在為字段val2創建索引但是使用val字段作為分區的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即“前綴索引”,指索引鍵與分區鍵是相同的,Oracle無法創建非前綴的全局分區索引。
?
2.3.?本地分區索引
只有分區表才能創建本地分區索引,本地分區索引始終使用與分區表相同的字段進行分區(不需要partition by子句),因此索引的分區與表的分區是一一對應的。我們看看語法:
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
這是因為在前一小節我們在這個列上創建過索引了,我們回去把tab_part_0321_2_idx移除,重新執行上面的語句便可創建成功,這說明跟global分區索引不同,local分區索引允許創建“非前綴索引”。
?
注:關于前面提到的本地前綴索引(local prefixed index)與本地非前綴索引(local non-prefixed index)的概念,有興趣的可以看看OTN的一些討論帖子,比如:https://forums.oracle.com/forums/thread.jspa?threadID=2150455&start=0&tstart=0
??
轉載于:https://www.cnblogs.com/morvenhuang/archive/2012/03/22/2411861.html
總結
以上是生活随笔為你收集整理的ORACLE HANDBOOK系列之十一:分区(Partition)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL Server 2005中的分区表
- 下一篇: 华为eudemon 200E的hrp双心