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