达梦数据库基础知识(十一)管理分区表和分区索引
在大型的企業應用或企業級的數據庫應用中,要處理的數據量通常達到TB級,對于這樣的大型表執行全表掃描或者DML操作時,效率是非常低的。
為了提高數據庫在大數據量讀寫操作和查詢時的效率,達夢數據庫提供了對表和索引進行分區的技術,把表和索引等數據庫對象中的數據分割成小的單位,分別存放在一個個單獨的段中,用戶對表的訪問轉化為對較小段的訪問,以改善大型應用系統的性能。
DM提供了水平分區方式。水平分區包括范圍、哈希和列表三種方式,企業可以使用合適的分區方法,如日期(范圍)、區域(列表),對大量數據進行分區。由于DM劃分的分區是相互獨立且可以存儲于不同的存儲介質上的,完全可滿足企業高可用性、均衡IO、降低維護成本、提高查詢性能的要求。
一、分區的概念
分區是指將表、索引等數據庫對象劃分為較小的可管理片段的技術,每一個片段稱為分區子表或分區索引。一個表被分區后,對表的查詢操作可以局限于某個分區進行,而不是整個表,這樣可以大大提高查詢速度。
DM支持對大表進行水平分區。例如,通訊公司將用戶通話記錄保存在一張表中,一年這個表產生40GB的數據。假設要對用戶的通話信息按照季度進行統計,那么這樣的統計需要在全表范圍內進行。如果對表按季度進行水平分區,那么每個分區的大小平均為10GB左右,這樣在進行統計時,只需在10GB的范圍內進行即可。
DM采用子表方式創建分區表,分區表作為分區主表,而每一個分區以一個子表實體存在,即每一個分區都是一個完整的表,一般命名為主表名_分區名。對于水平分區,子表跟主表具有相同的邏輯結構,即分區子表與分區主表有相同的列定義和約束定義。在DM分區表中,主表本身不存儲數據,所有數據只存儲在子表中,從而實現不同分區的完全獨立性。水平分區子表刪除后,會將子表上的數據一起刪除。
由于每一個分區都以一個子表作為實體,那么不同分區可以存儲于相同表空間,也可以位于不同的表空間中。將這些分區放在不同的表空間中具有以下的好處:
分區操作對現存的應用和運行在分區表上的標準DML語句來說是透明的。但是,可以通過在DML中使用分區子表名字來對應用進行編程,使其充分利用分區的優點。
二、分區的方法
達夢數據庫DM支持對表進行水平分區。對于水平分區,提供以下分區方式:
三、創建水平分區表
在創建表的語法中,使用partition子句指定分區方式和分區列,以及分區的名字等信息,即可創建分區表。而分區子表可以指定storage子句,設置子表的存儲屬性,如所屬表空間等;如果不指定,則繼承分區主表的存儲特性及表的其他屬性。同時,支持多級分區表。
水平分區表的ROWID與其主表屬性一致:LIST表的水平分區表的ROWID是物理的;普通表的水平分區表的ROWID是邏輯的,且每個子表的ROWID都是從1開始增長,但是最終返回前,ROWID的高字節會補充上子表序號。
1、創建范圍分區表
范圍分區是按照某個列或幾個列的值的范圍來創建分區,當用戶向表中寫入數據時,數據庫服務器將按照這些列上的值進行判斷,將數據寫入相應的分區中。
在創建范圍分區時,首先要指定分區列,即按照哪些列進行分區,然后為每個分區指定數據范圍。范圍分區支持MAXVALUE范圍值的使用,MAXVALUE相當于一個比任何值都大的值。范圍分區非常適用于數據按時間范圍組織的表,不同的時間段的數據屬于不同的分區。
例如,以下語句創建一個范圍分區表callinfo,用來記錄用戶的2010年的電話通訊信息,包括主叫號碼、被叫號碼、通話時間和時長,并且根據季度進行分區。
CREATE TABLE callinfo(
caller CHAR(15),
callee CHAR(15),
timeDATETIME,
durationINT
)
PARTITION BY RANGE(time)(
PARTITION p1 VALUES LESS THAN (‘2010-04-01’),
PARTITION p2VALUES LESS THAN (‘2010-07-01’),
PARTITION p3 VALUESLESS THAN (‘2010-10-01’),
PARTITION p4 VALUES EQU OR LESS THAN (‘2010-12-31’) --'2010-12-31’也可替換為MAXVALUE
);
值得注意的是,MAXVALUE之間無法比較大小。如下所示:
create table callinfo (
caller CHAR(15),
callee CHAR(15),
timeDATETIME,
durationINT
)
partition by range(caller, callee)
(
partition p1 values less than (‘a’, ‘b’),
partition p2 values lessthan (maxvalue, ‘d’),
partition p3 values less than (maxvalue,maxvalue)
); ----報“范圍分區值非遞增”錯誤,建分區表失敗
在創建分區表時,首先通過“PARTITION BY RANGE”子句指定分區的類型為范圍分區,然后在這個子句之后指定一個或多個列作為分區列,如callinfo的time字段。
表中的每個分區都可以通過“PARTITION”子句指定一個名稱。并且每一個分區都有一個范圍,通過“VALUES LESS THAN”子句可以指定上界,而它的下界是前一個分區的上界。如分區p2的time字段取值范圍是[‘2010-04-01’, ‘2010-07-01’)。如果通過“VALUES EQUOR LESS THAN”指定上界,即該分區包含上界值,如分區p4的time字段取值范圍是[‘2010-10-01’, ‘2010-12-31’]。另外,可以對每一個分區指定storage子句,不同分區可存儲在不同表空間中。
在創建范圍分區表時,可通過“INTERVAL <間隔表達式>”子句將該范圍分區表指定為間隔分區表。當對間隔分區表中的數據進行插入或更新操作時,若新的數據無法匹配現有的分區子表,則系統將自動以用戶指定的現有分區的末尾臨界值為起始值,以<間隔表達式>指定的值為間隔值創建一個可以匹配新數據的間隔分區。用戶可通過查看系統表SYSHPARTTABLEINFO來獲取新建分區的分區表ID以及分區名等信息。該功能可方便數據庫管理員對分區表的管理。
如果分區表包含多個分區列,采用多列比較方式定位匹配分區。首先,比較第一個分區列值,如果第一列值在范圍之內,就以第一列為依據進行分區;如果第一列值處于邊界值,那么需要比較第二列的值,根據第二列為依據進行分區;如果第二列的值也處于邊界值,需要繼續比較后續分區列值,以此類推,直到確定目標分區為止。匹配過程參看表15.1。
分區列匹配插入記錄 分區范圍值
(10,10,10) (20,20,20) (30,30,30)
(5,100,200) 滿足
(10,10,11) 滿足
(31,1,1) 不滿足 不滿足 不滿足
一般來說,對于數字型或者日期型的數據,適合采用范圍分區的方法;而對于字符型數據,取值比較固定的,則適合于采用LIST分區的方法。
例如,創建一個產品銷售記錄表sales,記錄產品的銷量情況。由于產品只在幾個固定的城市銷售,所以可以按照銷售城市對該表進行分區。
CREATE TABLE sales(
sales_idINT,
salemanCHAR(20),
saledateDATETIME,
cityCHAR(10)
)
PARTITION BY LIST(city)(
PARTITION p1 VALUES (‘北京’, ‘天津’),
PARTITION p2 VALUES (‘上海’, ‘南京’, ‘杭州’),
PARTITION p3VALUES (‘武漢’, ‘長沙’),
PARTITION p4 VALUES (‘廣州’, ‘深圳’)
);
在創建LIST分區時,通過“PARTITION BY LIST”子句指定對表進行LIST分區,然后在每個分區中分區列的取值通過VALUES子句指定。當用戶向表插入數據時,只要分區列的數據與VALUES子句指定的數據之一相等,該行數據便會寫入相應的分區子表中。注意的是,LIST分區的分區鍵必須唯一。
3、創建哈希分區表
在很多情況下,用戶無法預測某個列上的數據變化范圍,因而無法實現創建固定數量的范圍分區或LIST分區。
在這種情況下,DM哈希分區提供了一種在指定數量的分區中均等地劃分數據的方法,基于分區鍵的散列值將行映射到分區中。當用戶向表中寫入數據時,數據庫服務器將根據一個哈希函數對數據進行計算,把數據均勻地分布在各個分區中。在哈希分區中,用戶無法預測數據將被寫入哪個分區中。
現在重新考慮產品銷售表的例子。如果銷售城市不是相對固定的,而是遍布全國各地,這時很難對表進行LIST分區。如果為該表進行哈希分區,可以很好地解決這個問題。
CREATE TABLE sales01(
sales_idINT,
salemanCHAR(20),
saledateDATETIME,
cityCHAR(10)
)
PARTITION BY HASH(city)(
PARTITION p1,
PARTITION p2,
PARTITION p3,
PARTITION p4
);
如果不需指定分區表名,可以通過指定哈希分區個數來建立哈希分區表。
CREATE TABLE sales02(
sales_idINT,
salemanCHAR(20),
saledateDATETIME,
cityCHAR(10)
)
PARTITION BY HASH(city)
PARTITIONS 4 STORE IN (ts1, ts2, ts3, ts4);
PARTITIONS后的數字表示哈希分區的分區數,STORE IN子句中指定了哈希分區依次使用的表空間。使用這種方式建立的哈希分區表分區名是匿名的,DM統一使用DMHASHPART+分區號(從0開始)作為分區名。例如,需要查詢sales第一個分區的數據,可執行以下語句:
SELECT *FROM sales02PARTITION (dmhashpart0);
4、創建多級分區表
在很多情況下,經過一次分區并不能精確地對數據進分類,這時需要多級分區表。
例如,創建一個產品銷售記錄表sales,記錄產品的銷量情況。由于產品需要按地點和銷售時間進行統計,則可以對該表進行LIST-RANGE分區。
DROP TABLE SALES;
CREATE TABLESALES(
SALES_IDINT,
SALEMANCHAR(20),
SALEDATEDATETIME,
CITYCHAR(10)
)
PARTITION BY LIST(CITY)
SUBPARTITION BY RANGE(SALEDATE) SUBPARTITION TEMPLATE(
SUBPARTITION P11 VALUES LESS THAN (‘2012-04-01’),
SUBPARTITION P12 VALUES LESS THAN (‘2012-07-01’),
SUBPARTITION P13 VALUES LESS THAN (‘2012-10-01’),
SUBPARTITION P14 VALUES EQU OR LESS THAN (MAXVALUE))
(
PARTITION P1 VALUES (‘北京’, ‘天津’)
(
SUBPARTITION P11_1VALUES LESS THAN (‘2012-10-01’),
SUBPARTITION P11_2VALUES EQU OR LESS THAN (MAXVALUE)
),
PARTITION P2 VALUES (‘上海’, ‘南京’, ‘杭州’),
PARTITION P3 VALUES (DEFAULT)
);
在創建多級分區表時,指定了子分區模板,同時子分區P1自定義了子分區描述P11_1和P11_2。P1有兩個子分區P11_1和P11_2。而子分區P2和P3有四個子分區P11、P12、P13和P14。DM支持最多八層多級分區。
下面給出一個三級分區的例子,更多級別的分區表的建表語句語法類推。
CREATE TABLE STUDENT(NAME VARCHAR(20), AGE INT, SEX VARCHAR(10) CHECK (SEX IN (‘MAIL’,‘FEMAIL’)), GRADE INT CHECK (GRADE IN (7,8,9)))
PARTITION BY LIST(GRADE)
SUBPARTITION BY LIST(SEX) SUBPARTITION TEMPLATE
(
SUBPARTITIONQ1 VALUES(‘MAIL’),
SUBPARTITION Q2 VALUES(‘FEMAIL’)
),
SUBPARTITION BY RANGE(AGE) SUBPARTITION TEMPLATE
(
SUBPARTITION R1 VALUES LESS THAN (12),
SUBPARTITION R2 VALUES LESS THAN (15),
SUBPARTITION R3 VALUES LESS THAN (MAXVALUE)
)
(
PARTITION P1 VALUES (7),
PARTITION P2 VALUES (8),
PARTITION P3 VALUES (9)
);
四、在水平分區表建立索引
DM支持對水平分區表建立普通索引、唯一索引、聚集索引和函數索引。
創建水平分區表時,若表的PRIMARY KEY未包含所有分區列,系統會自動創建全局索引,否則自動創建局部索引。創建全局索引時,在水平分區表的主表創建全局索引,每個分區子表的數據都被索引在同一個B樹中,并在每個子表創建全局本地索引,與主表共用一個B樹。例如,下面的語句在創建水平分區表test時會自動創建一個全局索引。
CREATE TABLE test(c1 INT, c2 INT PRIMARY KEY) PARTITION BY HASH(c1)
PARTITIONS 2;
當使用創建索引語句在水平分區表上創建索引時,若指定GLOBAL關鍵字,創建全局索引,否則創建為局部索引。在水平分區表上創建唯一索引時,全局唯一索引總是可以創建的,若要創建非全局唯一索引,則要求索引鍵包含所有的分區鍵。這是因為對于局部索引,每一個分區子表都會建立一個索引分區,負責索引分區子表的數據。由于每個索引分區只負責索引本分區上的數據,其他分區上的數據無法維護,只有當分區鍵都包含在索引鍵中時,才能對分區主表保證索引鍵唯一。
例如,在sales表上的saledate列上建立局部索引,在ind_sales_city列上建立非全局唯一索引。
CREATE INDEX ind_sales_saldate ON sales(saledate);
CREATE UNIQUE INDEX ind_sales_city ON sales(city);
另外,只能在水平分區表上創建局部聚集索引,不能創建全局聚集索引;不能在水平分區表上創建局部唯一函數索引;HUGE水平分區表不支持全局索引。
五、維護水平分區表
創建水平分區表后,DM提供了對分區表的修改,功能包括:
在DM中,由于局部索引反映基礎表的結構,因此當對表的分區和子分區進行修改操作時,會自動地對局部索引進行相應的修改。
(一)增加分區
DM支持用ALTER TABLE ADD PARTITION語句將新分區增加到最后一個現存分區的后面。例如,范圍分區表callinfo現需要記錄用戶的2011年的第一季度的通訊信息,那么,需要為2011年第一季度增加一個分區,并將其存儲在表空間ts5中。
ALTERTABLE callinfo
ADD PARTITION p5 VALUES LESS THAN (‘2011-4-1’) STORAGE (ON ts5);
對于范圍分區,增加分區必須在最后一個分區范圍值的后面添加,要想在表的開始范圍或中間增加分區,應使用SPLIT PARTITION語句。
對于LIST分區,增加分區包含的離散值不能已存在于某個分區中。例如,為LIST分區表sales添加一個分區管理拉薩和呼和浩特的銷售情況。
ALTER TABLE sales
ADD PARTITION p5 VALUES (‘拉薩’, ‘呼和浩特’) STORAGE (ON ts5);
可以對范圍分區和LIST分區增加分區,存儲選項HASHPARTMAP為1的HASH分區表也支持增加分區。增加分區不會影響分區索引,因為分區索引只是局部索引,新增分區僅是新增分區子表,并更新分區主表的分區信息,其他分區并不發生改變。
(二) 刪除分區
DM支持用ALTER TABLE DROP PARTITION語句將分區刪除。例如,范圍分區表callinfo現需要刪除記錄用戶的2011年的第一季度的通訊信息,那么,只需刪除callinfo的分區p1即可。
ALTER TABLEcallinfo DROP PARTITION p1;
只能對范圍分區和LIST分區進行刪除分區,哈希分區不支持刪除分區。跟增加分區一樣,刪除分區不會影響分區索引,因為分區索引只是局部索引,刪除分區僅是刪除分區子表,并更新分區主表的分區信息,其他分區并不發生改變。
(三)交換分區
假設上文提到的callinfo表是用于維護最近12個月的用戶通話信息,超過12個月的訂單需要遷移到該季度的通話信息歷史表中,并且每一個季度都有一個相應的歷史表。如果沒有使用水平分區,需要較多的刪除和插入操作,并產生大量的redo和undo日志。
如果使用分區表,如上文提到的callinfo,只需使用交換分區即可完成以上功能。例如,2011年第二季度已到了,需刪除2010年第二季度的通話記錄,因此,可通過以下腳本來實現:
CREATE TABLE callinfo_2011Q2(
caller CHAR(15),
callee CHAR(15),
timeDATETIME,
durationINT
);
–交換分區
ALTER TABLE callinfoEXCHANGE PARTITION p2WITH TABLE callinfo_2011Q2;
–刪除原分區
ALTER TABLEcallinfo DROP PARTITION p2;
–新增分區,記錄2011年第二季度通話記錄
ALTER TABLE callinfo
ADD PARTITION p6 VALUES LESS THAN (‘2011-7-1’) STORAGE (ON ts2);
通過交換分區實現分區p2和新建表callinfo_2011Q2的數據交換,表callinfo_2011Q2將得到2010年第二季度的通話記錄,而分區p2數據將被清空。交換分區采用數據字典信息交換的技術,幾乎不涉及IO操作,因此效率非常高。
僅范圍分區和LIST分區支持交換分區,哈希分區表不支持。并且分區交換要求分區表跟交換表具有相同的結構(相同的表類型、相同的BRANCH選項、相同的列結構、相同的索引、相同的分布方式),分區交換但并不會校驗數據,如交換表的數據是否符合分區范圍等,即不能保證分區交換后的分區上的數據符合分區范圍。
進行交換的兩張表,如果包含加密列,對應的加密列要求加密信息完全一致。
(四)合并分區
要想將兩個范圍分區的內容融合到一個分區,就要使用ALTERTABLE MERGE PARTITION語句。如果分區的數據很少,或相對其他分區某些分區的數據量較少,導致I/O不均衡,就可以考慮使用合并分區。
例如,可將callinfo的2010第3季度和第4季度合并成一個分區:
ALTER TABLE callinfo MERGE PARTITIONS p3, p4 into partition p3_4;
僅范圍分區表和LIST分區表支持合并分區。其中,合并的RANGE分區必須是范圍相鄰的兩分區。
多級分區表進行MERGE合并的注意事項:
合并分區會導致數據的重組和分區索引的重建,因此,合并分區可能會比較耗時,所需時間取決于分區數據量的大小。
(五)拆分分區
ALTER TABLE語句的SPLIT PARTITION子句被用于將一分區中的內容重新劃分成兩個新的分區。當一個分區變得太大以至于要用很長時間才能完成備份、恢復或維護操作時,就應考慮做分割分區的工作,還可以用SPLIT PARTITION子句來重新劃分I/O負載。
例如,將合并后的p3_4拆分為原兩分區p3和p4,分別記錄2010年第三和第四季度的通話記錄。
ALTER TABLE callinfo SPLIT PARTITION p3_4 AT (‘2010-9-30’) INTO (PARTITION p3, PARTITION p4);
僅范圍分區表和LIST分區表支持拆分分區。拆分分區另一個重要用途是作為新增分區的補充。通過拆分分區,可以對范圍分區表的開始或中間范圍添加分區。
多級分區表進行拆分SPLIT注意事項:
拆分分區會導致數據的重組和分區索引的重建,因此,拆分分區可能會比較耗時,所需時間取決于分區數據量的大小。
(六) 水平分區表的限制
DM水平分區表有如下限制條件:
log2MAX_EP_SITES)。比如:當MAX_EP_SITES為默認值64時,分區總數上限為1024;
資料來源:https://eco.dameng.com
總結
以上是生活随笔為你收集整理的达梦数据库基础知识(十一)管理分区表和分区索引的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python爬虫下载文件
- 下一篇: linux cmake编译源码,linu