GP--表分區管理(二)

1、定義日期範圍分區表

日期範圍分區表使用單個date或者timestamp字段作爲分區鍵。

可以通過使用START值、 END值和EVERY子句定義分區增量讓GPDB自動產生分區。

缺省情況下, START值總是被包含而END值總是被排除(左閉右開)。

CREATE TABLE sales 
(
id int
, date date
, amt decimal(10,2)
) 
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
( 	
	START	(date '2018-01-01') INCLUSIVE
	END		(date '2019-01-01') EXCLUSIVE
	EVERY 	(INTERVAL '1 day')
);

不過也可以爲每個分區單獨指定名稱。比如:

CREATE TABLE sales (id int, date date, amt decimal(10,2))
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
(   PARTITION Jan08 START (date '2008-01-01') INCLUSIVE ,
    PARTITION Feb08 START (date '2008-02-01') INCLUSIVE ,
    PARTITION Mar08 START (date '2008-03-01') INCLUSIVE ,
    PARTITION Apr08 START (date '2008-04-01') INCLUSIVE ,
    PARTITION May08 START (date '2008-05-01') INCLUSIVE ,
    PARTITION Jun08 START (date '2008-06-01') INCLUSIVE ,
    PARTITION Jul08 START (date '2008-07-01') INCLUSIVE ,
    PARTITION Aug08 START (date '2008-08-01') INCLUSIVE ,
    PARTITION Sep08 START (date '2008-09-01') INCLUSIVE ,
    PARTITION Oct08 START (date '2008-10-01') INCLUSIVE ,
    PARTITION Nov08 START (date '2008-11-01') INCLUSIVE ,
    PARTITION Dec08 START (date '2008-12-01') INCLUSIVE END (date '2009-01-01') EXCLUSIVE 
);

上面的分區的範圍都是連續的,如果不連續需要指定end值。

2、定義數字範圍分區表

數字範圍分區表使用單個數字列作爲分區鍵。例如:

CREATE TABLE rank (id int
, rank int
, year int
, gender char(1)
, count int)
DISTRIBUTED BY (id)
PARTITION BY RANGE (year)
( START (2001) END (2008) EVERY (1),
  DEFAULT PARTITION extra 
);

3、定義列表分區表

列表分區表可以使用任何數據類型的列作爲分區鍵,分區規則使用等值比較。
列表分區可以使用多個COLUMN(組合起來)作爲分區鍵,而範圍分區只允許使用單獨COLUMN作爲分區鍵。對於列表分區,必須爲每個分區指定相應的值。

CREATE TABLE rank (id int, rank int, year int, gender char(1), count int )
DISTRIBUTED BY (id)
PARTITION BY LIST (gender)
( 
PARTITION girls VALUES ('F'),
PARTITION boys VALUES ('M'),
DEFAULT PARTITION other 
);

4、定義多級分區表

使用SUBPARTITION TEMPLATE來確保每個分區具有相同的子分區結構,尤其是對那些後增加的分區來說。

CREATE TABLE sales (trans_id int, date date, amount decimal(9,2), region text)
DISTRIBUTED BY (trans_id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
  SUBPARTITION TEMPLATE
  ( 
    SUBPARTITION usa VALUES ('usa'),
    SUBPARTITION asia VALUES ('asia'),
    SUBPARTITION europe VALUES ('europe'),
    DEFAULT SUBPARTITION other_regions
  )
( START (date '2008-01-01') INCLUSIVE END (date '2009-01-01') EXCLUSIVE
  EVERY (INTERVAL '1 month'), 
  DEFAULT PARTITION outlying_dates 
);

下面是一個3級分區表的例子,這裏表sales被分區爲年、月、區域。 SUBPARTITION TEMPLATE子句確保每個年分區有相同的子分區結構。
另外,每個級別的分區都有一個默認分區:

CREATE TABLE sales (id int, year int, month int, day int, region text) DISTRIBUTED BY (id)
PARTITION BY RANGE (year)
SUBPARTITION BY RANGE (month)
  SUBPARTITION TEMPLATE 
  (
    START (1) END (13) EVERY (1),
    DEFAULT SUBPARTITION other_months 
  )
SUBPARTITION BY LIST (region)
  SUBPARTITION TEMPLATE 
  (
    SUBPARTITION usa VALUES ('usa'),
    SUBPARTITION europe VALUES ('europe'),
    SUBPARTITION asia VALUES ('asia'),
    DEFAULT SUBPARTITION other_regions 
  )
( START (2002) END (2010) EVERY (1), 
  DEFAULT PARTITION outlying_years 
);

將現有表分區

對已經創建的表是不能分區的。只能在CREATE TABLE的時候做分區。要想對現有的表做分區,只能重新創建一個分區表、重新裝載數據到新的分區表中、刪掉舊錶然後把新的分區表改爲舊錶的名稱。還必須重新對TABLE做授權。

CREATE TABLE sales2 (LIKE sales)
PARTITION BY RANGE (date)
( START (date '1998-01-01') INCLUSIVE END (date '2002-01-01') EXCLUSIVE
  EVERY (INTERVAL '1 month') 
);
INSERT INTO sales2 SELECT * FROM sales;
DROP TABLE sales;
ALTER TABLE sales2 RENAME TO sales;
GRANT ALL PRIVILEGES ON sales TO admin;
GRANT SELECT ON sales TO guest;

分區表的限制

主鍵或者唯一約束必須包含表上的所有分區鍵。而唯一索引可以不包含分區鍵,但是,其只對一個分區強制有效,而不是對整個分區表有效。

裝載分區表

一旦創建了分區表,頂級表總是空的。數據值儲存在最低層的表中。在多級分區表中,僅僅在層級最低的子分區中有數據。

在運行期間,查詢規劃器會掃描整個TABLE的層級結構並使用CHECK約束適配查詢條件來決定哪些子表需要被掃描。

默認分區(只要該層級中存在)總是會被掃描。如果默認分區中包含數據,其會拖慢整體的掃表時間。

如果有必要,還可以直接把數據裝載到子表中。還可以先創建一箇中間表、裝載數據、然後與分區表進行分區交換。這種分區交換的性能高於直接的COPY和INSERT。

查看分區設計

要查看分區表的設計情況,通過pg_partitions視圖查看。

SELECT 
partitionboundary
, partitiontablename
, partitionname
, partitionlevel
, partitionrank
FROM pg_partitions WHERE tablename='sales2';
 
pg_partition_templates - 用以創建SUBPARTITION的SUBPARTITION template
pg_partition_columns – 用於分區的分區鍵

維護分區表

必須使用ALTER TABLE命令從頂級表來維護分區

  1. 最常見的場景是根據日期範圍的設計來維護數據時,刪除舊分區並添加一個新的分區。
  2. 把舊的分區交換爲壓縮AO表以節省空間。

若在父表中存在默認分區,添加分區的操作只能是從默認分區拆分出一個新的分區。

由於分區不要求有名稱,若分區沒有名稱,下面的表達式仍可以指定一個分區:

PARTITION FOR (value) or PARTITION FOR(RANK(number))

(1) 添加新分區

如果原有的分區表包含了subpartition template設計,新增的分區將根據該模版創建子分區。

CREATE TABLE sales (trans_id int, date char(8), amount decimal(9,2), region text)
DISTRIBUTED BY (trans_id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
  SUBPARTITION TEMPLATE
  ( 
    SUBPARTITION usa VALUES ('usa'),
    SUBPARTITION asia VALUES ('asia'),
    SUBPARTITION europe VALUES ('europe'),
    DEFAULT SUBPARTITION other_regions
  )
( START ('2008-01-01') INCLUSIVE END ('2009-01-01') EXCLUSIVE
  EVERY (INTERVAL '1 month'), 
  DEFAULT PARTITION outlying_dates 
);
 
ALTER TABLE sales ADD PARTITION
START (date '2009-02-01') INCLUSIVE
END (date '2009-03-01') EXCLUSIVE;

如果在創建TABLE時沒有subpartition template,在新增分區時需要定義子分區:

ALTER TABLE sales ADD PARTITION
START (date '2009-02-01') INCLUSIVE
END (date '2009-03-01') EXCLUSIVE
( SUBPARTITION usa VALUES ('usa'),
SUBPARTITION asia VALUES ('asia'),
SUBPARTITION europe VALUES ('europe') );

子表的名稱格式如下:

<父表名稱>_<分區層級>prt<分區名稱>

子表的名稱不能通過直接執行ALTER表名來實現。但修改頂級表的名稱,該改變將會影響所有相關的分區表。

添加缺省分區

ALTER TABLE sales ADD DEFAULT PARTITION other;

如果是多級分區表, 同一層次中的每個分區都需要一個默認分區。

ALTER TABLE sales ALTER PARTITION FOR (RANK(1)) ADD DEFAULT PARTITION other;
ALTER TABLE sales ALTER PARTITION FOR (RANK(2)) ADD DEFAULT PARTITION other;
ALTER TABLE sales ALTER PARTITION FOR (RANK(3)) ADD DEFAULT PARTITION other;

RANK(partitionrank)指的是範圍分區同一層級中的順序。partitionrank可參見pg_partition表。

(2)刪除分區

ALTER TABLE sales DROP PARTITION FOR (RANK(1));

注意: 在將RANK(1)的分區刪除後,其餘分區的partitionrank值仍然是從1開始的連續編號。 編號的順序按照分區字段的值由小到大從1開始排序。
不管分區是否連續(中間有值不匹配分區),或者隨意的修改分區定義。

(3)清空分區數據

在清空一個包含子分區的分區時,其所有相關子分區的數據都自動被清空。

ALTER TABLE sales TRUNCATE PARTITION FOR (RANK(1));

(4)交換分區:

CREATE TABLE jan08 (LIKE sales) WITH (appendonly=true);
INSERT INTO jan08 SELECT * FROM sales_1_prt_1 ;
ALTER TABLE sales EXCHANGE PARTITION FOR (DATE '2008-01-01') WITH TABLE jan08

(5)拆分分區

拆分分區是將現有的一個分區分成兩個分區。 使用ALTER TABLE命令來拆分分區。
只能拆分最低層級的分區表(只有包含數據的分區可以拆分)。
指定的分割值對應的數據將進入後面一個分區(就是STAER爲INCLUSIVE)。

ALTER TABLE sales SPLIT PARTITION FOR ('2008-01-01')
AT ('2008-01-16') INTO (PARTITION jan081to15, PARTITION jan0816to31);

如果分區表有默認分區,要添加新的分區只能從默認分區拆分。而且只能從最低層級分區的默認分區拆分(只有包含數據的分區可以拆分)。
在使用INTO子句時,第2個分區名稱必須是已經存在的默認分區。

ALTER TABLE sales SPLIT DEFAULT PARTITION
START ('2009-01-01') INCLUSIVE
END ('2009-02-01') EXCLUSIVE
INTO (PARTITION jan09, default partition);

(6)修改子分區模版

使用ALTER TABLE SET SUBPARTITION TEMPLATE命令來修改現有分區表的子分區模版。 在修改了子分區模版之後添加的分區,其子分區將按照新的模版產生。已經存在的分區不會被修改。

ALTER TABLE sales SET SUBPARTITION TEMPLATE
(   SUBPARTITION usa VALUES ('usa'),
    SUBPARTITION asia VALUES ('asia'),
    SUBPARTITION europe VALUES ('europe'),
    SUBPARTITION africa VALUES ('africa')
    DEFAULT SUBPARTITION other 
);
ALTER TABLE sales ADD PARTITION sales_prt_3
START ('2009-03-01') INCLUSIVE END ('2009-04-01') EXCLUSIVE;

這個例子在一級分區有默認分區時是不能執行的,要查看效果,先刪除默認分區。
要刪除子分區模版,使用SET SUBPARTITION TEMPLATE並使用空的參數來完成。

ALTER TABLE sales SET SUBPARTITION TEMPLATE ();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章