云服务器内容精选

  • 列表分区 列表分区(List Partition)能够通过在每个分区的描述中为分区键指定离散值列表来显式控制行如何映射到分区。列表分区的优势在于可以以枚举分区值方式对数据进行分区,可以对无序和不相关的数据集进行分组和组织。对于未定义在列表中的分区键值,可以使用默认分区(DEFAULT)来进行数据的保存,这样所有未映射到任何其他分区的行都不会生成错误。示例如下: gaussdb=# CREATE TABLE bmsql_order_line ( ol_w_id INTEGER NOT NULL, ol_d_id INTEGER NOT NULL, ol_o_id INTEGER NOT NULL, ol_number INTEGER NOT NULL, ol_i_id INTEGER NOT NULL, ol_delivery_d TIMESTAMP, ol_amount DECIMAL(6,2), ol_supply_w_id INTEGER, ol_quantity INTEGER, ol_dist_info CHAR(24) ) PARTITION BY LIST(ol_d_id) ( PARTITION p0 VALUES (1,4,7), PARTITION p1 VALUES (2,5,8), PARTITION p2 VALUES (3,6,9), PARTITION p3 VALUES (DEFAULT) ); --清理示例 gaussdb=# DROP TABLE bmsql_order_line; 上述例子和之前给出的哈希分区的例子类似,同样通过ol_d_id列进行分区,但是在List分区中直接通过对ol_d_id的可能取值范围进行限定,不在列表中的数据会进入p3分区(DEFAULT)。相比哈希分区,List列表分区对分区键的可控性更好,往往能够准确的将目标数据保存在预想的分区中,但是如果列表值较多在分区定义时变得麻烦,该情况下推荐使用Hash分区。List、Hash分区往往都是处理无序、不相关的数据集进行分组和组织。 列表分区的分区键最多支持16列。如果分区键定义为1列,子分区定义时List列表中的枚举值不允许为NULL值;如果分区键定义为多列,子分区定义时List列表中的枚举值允许有NULL值。 父主题: 分区策略
  • 二级分区 二级分区(Sub Partition,也叫组合分区)是基本数据分区类型的组合,将表通过一种数据分布方法进行分区,然后使用第二种数据分布方式将每个分区进一步细分为子分区。给定分区的所有子分区表示数据的逻辑子集。常见的二级分区组合如下所示: Range-Range Range-List Range-Hash List-Range List-List List-Hash Hash-Range Hash-List Hash-Hash 示例如下: gaussdb=# --Range-Range CREATE TABLE t_range_range ( c1 INT, c2 INT, c3 INT ) PARTITION BY RANGE (c1) SUBPARTITION BY RANGE (c2) ( PARTITION p1 VALUES LESS THAN (10) ( SUBPARTITION p1sp1 VALUES LESS THAN (5), SUBPARTITION p1sp2 VALUES LESS THAN (10) ), PARTITION p2 VALUES LESS THAN (20) ( SUBPARTITION p2sp1 VALUES LESS THAN (15), SUBPARTITION p2sp2 VALUES LESS THAN (20) ) ); DROP TABLE t_range_range; --Range-List CREATE TABLE t_range_list ( c1 INT, c2 INT, c3 INT ) PARTITION BY RANGE (c1) SUBPARTITION BY LIST (c2) ( PARTITION p1 VALUES LESS THAN (10) ( SUBPARTITION p1sp1 VALUES (1, 2), SUBPARTITION p1sp2 VALUES (3, 4) ), PARTITION p2 VALUES LESS THAN (20) ( SUBPARTITION p2sp1 VALUES (1, 2), SUBPARTITION p2sp2 VALUES (3, 4) ) ); DROP TABLE t_range_list; --Range-Hash CREATE TABLE t_range_hash ( c1 INT, c2 INT, c3 INT ) PARTITION BY RANGE (c1) SUBPARTITION BY HASH (c2) SUBPARTITIONS 2 ( PARTITION p1 VALUES LESS THAN (10), PARTITION p2 VALUES LESS THAN (20) ); DROP TABLE t_range_hash; --List-Range CREATE TABLE t_list_range ( c1 INT, c2 INT, c3 INT ) PARTITION BY LIST (c1) SUBPARTITION BY RANGE (c2) ( PARTITION p1 VALUES (1, 2) ( SUBPARTITION p1sp1 VALUES LESS THAN (5), SUBPARTITION p1sp2 VALUES LESS THAN (10) ), PARTITION p2 VALUES (3, 4) ( SUBPARTITION p2sp1 VALUES LESS THAN (5), SUBPARTITION p2sp2 VALUES LESS THAN (10) ) ); DROP TABLE t_list_range; --List-List CREATE TABLE t_list_list ( c1 INT, c2 INT, c3 INT ) PARTITION BY LIST (c1) SUBPARTITION BY LIST (c2) ( PARTITION p1 VALUES (1, 2) ( SUBPARTITION p1sp1 VALUES (1, 2), SUBPARTITION p1sp2 VALUES (3, 4) ), PARTITION p2 VALUES (3, 4) ( SUBPARTITION p2sp1 VALUES (1, 2), SUBPARTITION p2sp2 VALUES (3, 4) ) ); DROP TABLE t_list_list; --List-Hash CREATE TABLE t_list_hash ( c1 INT, c2 INT, c3 INT ) PARTITION BY LIST (c1) SUBPARTITION BY HASH (c2) SUBPARTITIONS 2 ( PARTITION p1 VALUES (1, 2), PARTITION p2 VALUES (3, 4) ); DROP TABLE t_list_hash; --Hash-Range CREATE TABLE t_hash_range ( c1 INT, c2 INT, c3 INT ) PARTITION BY HASH (c1) PARTITIONS 2 SUBPARTITION BY RANGE (c2) ( PARTITION p1 ( SUBPARTITION p1sp1 VALUES LESS THAN (5), SUBPARTITION p1sp2 VALUES LESS THAN (10) ), PARTITION p2 ( SUBPARTITION p2sp1 VALUES LESS THAN (5), SUBPARTITION p2sp2 VALUES LESS THAN (10) ) ); DROP TABLE t_hash_range; --Hash-List CREATE TABLE t_hash_list ( c1 INT, c2 INT, c3 INT ) PARTITION BY HASH (c1) PARTITIONS 2 SUBPARTITION BY LIST (c2) ( PARTITION p1 ( SUBPARTITION p1sp1 VALUES (1, 2), SUBPARTITION p1sp2 VALUES (3, 4) ), PARTITION p2 ( SUBPARTITION p2sp1 VALUES (1, 2), SUBPARTITION p2sp2 VALUES (3, 4) ) ); DROP TABLE t_hash_list; --Hash-Hash CREATE TABLE t_hash_hash ( c1 INT, c2 INT, c3 INT ) PARTITION BY HASH (c1) PARTITIONS 2 SUBPARTITION BY HASH (c2) SUBPARTITIONS 2 ( PARTITION p1, PARTITION p2 ); DROP TABLE t_hash_hash; Interval分区看成是范围分区的一种特殊形式,目前不支持二级分区场景中定义Interval分区。 二级分区表的一级分区和二级分区分区键均只支持1列。 父主题: 分区策略
  • 范围分区 范围分区(Range Partition)根据为每个分区建立的分区键的值范围将数据映射到分区。范围分区是生产系统中最常见的分区类型,通常在以时间维度(Date、Time Stamp)描述数据场景中使用。范围分区有两种语法格式,示例如下: VALUES LESS THAN的语法格式 对于从句是VALUE LESS THAN的语法格式,范围分区策略的分区键最多支持16列。 单列分区键示例如下: gaussdb=# CREATE TABLE range_sales_single_key ( product_id INT4 NOT NULL, customer_id INT4 NOT NULL, time DATE, channel_id CHAR(1), type_id INT4, quantity_sold NUMERIC(3), amount_sold NUMERIC(10,2) ) PARTITION BY RANGE (time) ( PARTITION date_202001 VALUES LESS THAN ('2020-02-01'), PARTITION date_202002 VALUES LESS THAN ('2020-03-01'), PARTITION date_202003 VALUES LESS THAN ('2020-04-01'), PARTITION date_202004 VALUES LESS THAN ('2020-05-01') ); --清理示例 gaussdb=# DROP TABLE range_sales_single_key; 其中date_202002表示2020年2月的分区,将包含分区键值从2020年2月1日到2020年2月29日的数据。 每个分区都有一个VALUES LESS子句,用于指定分区的非包含上限。大于或等于该分区键的任何值都将添加到下一个分区。除第一个分区外,所有分区都具有由前一个分区的VALUES LESS子句指定的隐式下限。可以为最高分区定义MAXVALUE关键字,MAXVALUE表示一个虚拟无限值,其排序高于分区键的任何其他可能值,包括空值。 多列分区键示例如下: gaussdb=# CREATE TABLE range_sales ( c1 INT4 NOT NULL, c2 INT4 NOT NULL, c3 CHAR(1) ) PARTITION BY RANGE (c1,c2) ( PARTITION p1 VALUES LESS THAN (10,10), PARTITION p2 VALUES LESS THAN (10,20), PARTITION p3 VALUES LESS THAN (20,10) ); gaussdb=# INSERT INTO range_sales VALUES(9,5,'a'); gaussdb=# INSERT INTO range_sales VALUES(9,20,'a'); gaussdb=# INSERT INTO range_sales VALUES(9,21,'a'); gaussdb=# INSERT INTO range_sales VALUES(10,5,'a'); gaussdb=# INSERT INTO range_sales VALUES(10,15,'a'); gaussdb=# INSERT INTO range_sales VALUES(10,20,'a'); gaussdb=# INSERT INTO range_sales VALUES(10,21,'a'); gaussdb=# INSERT INTO range_sales VALUES(11,5,'a'); gaussdb=# INSERT INTO range_sales VALUES(11,20,'a'); gaussdb=# INSERT INTO range_sales VALUES(11,21,'a'); gaussdb=# SELECT * FROM range_sales PARTITION (p1); c1 | c2 | c3 ----+----+---- 9 | 5 | a 9 | 20 | a 9 | 21 | a 10 | 5 | a (4 rows) gaussdb=# SELECT * FROM range_sales PARTITION (p2); c1 | c2 | c3 ----+----+---- 10 | 15 | a (1 row) gaussdb=# SELECT * FROM range_sales PARTITION (p3); c1 | c2 | c3 ----+----+---- 10 | 20 | a 10 | 21 | a 11 | 5 | a 11 | 20 | a 11 | 21 | a (5 rows) --清理示例 gaussdb=# DROP TABLE range_sales; 多列分区的分区规则如下: 从第一列开始比较。 如果插入的值当前列小于分区当前列边界值,则直接插入。 如果插入的当前列等于分区当前列的边界值,则比较插入值的下一列与分区下一列边界值的大小。 如果插入的当前列大于分区当前列的边界值,则换下一个分区进行比较。 START END语法格式 对于从句是START END语法格式,范围分区策略的分区键最多支持1列。 示例如下: -- 创建表空间 gaussdb=# CREATE TABLESPACE startend_tbs1 LOCATION '/home/omm/startend_tbs1'; gaussdb=# CREATE TABLESPACE startend_tbs2 LOCATION '/home/omm/startend_tbs2'; gaussdb=# CREATE TABLESPACE startend_tbs3 LOCATION '/home/omm/startend_tbs3'; gaussdb=# CREATE TABLESPACE startend_tbs4 LOCATION '/home/omm/startend_tbs4'; -- 创建临时schema gaussdb=# CREATE SCHEMA tpcds; gaussdb=# SET CURRENT_SCHEMA TO tpcds; -- 创建分区表,分区键是integer类型 gaussdb=# CREATE TABLE tpcds.startend_pt (c1 INT, c2 INT) TABLESPACE startend_tbs1 PARTITION BY RANGE (c2) ( PARTITION p1 START(1) END(1000) EVERY(200) TABLESPACE startend_tbs2, PARTITION p2 END(2000), PARTITION p3 START(2000) END(2500) TABLESPACE startend_tbs3, PARTITION p4 START(2500), PARTITION p5 START(3000) END(5000) EVERY(1000) TABLESPACE startend_tbs4 ) ENABLE ROW MOVEMENT; -- 查看分区表信息 gaussdb=# SELECT relname, boundaries, spcname FROM pg_partition p JOIN pg_tablespace t ON p.reltablespace=t.oid and p.parentid='tpcds.startend_pt'::regclass ORDER BY 1; relname | boundaries | spcname -------------+------------+--------------- p1_0 | {1} | startend_tbs2 p1_1 | {201} | startend_tbs2 p1_2 | {401} | startend_tbs2 p1_3 | {601} | startend_tbs2 p1_4 | {801} | startend_tbs2 p1_5 | {1000} | startend_tbs2 p2 | {2000} | startend_tbs1 p3 | {2500} | startend_tbs3 p4 | {3000} | startend_tbs1 p5_1 | {4000} | startend_tbs4 p5_2 | {5000} | startend_tbs4 startend_pt | | startend_tbs1 (12 rows) --清理示例 gaussdb=# DROP TABLE tpcds.startend_pt; 父主题: 分区策略
  • 哈希分区 哈希分区(Hash Partition)基于对分区键使用哈希算法将数据映射到分区。使用的哈希算法为GaussDB内置哈希算法,在分区键取值范围不倾斜(no data skew)场景下,哈希算法在分区之间均匀分布行,使分区大小大致相同。因此哈希分区是实现分区间均匀分布数据的理想方法。哈希分区也是范围分区的一种易于使用的替代方法,尤其是当要分区的数据不是历史数据或没有明显的分区键时,示例如下: gaussdb=# CREATE TABLE bmsql_order_line ( ol_w_id INTEGER NOT NULL, ol_d_id INTEGER NOT NULL, ol_o_id INTEGER NOT NULL, ol_number INTEGER NOT NULL, ol_i_id INTEGER NOT NULL, ol_delivery_d TIMESTAMP, ol_amount DECIMAL(6,2), ol_supply_w_id INTEGER, ol_quantity INTEGER, ol_dist_info CHAR(24) ) --预先定义100个分区 PARTITION BY HASH(ol_d_id) ( PARTITION p0, PARTITION p1, PARTITION p2, … PARTITION p99 ); 上述例子中,bmsql_order_line表的ol_d_id进行了分区,ol_d_id列是一个identifier性质的属性列,本身并不带有时间或者某一个特定维度上的区分。使用哈希分区策略来对其进行分表处理则是一个较为理想的选择,相比其他分区类型,除了预先确保分区键没有过多数据倾斜(某一、某几个值重复度高),只需要指定分区键和分区数即可创建分区,同时还能够确保每个分区的数据均匀,提升了分区表的易用性。 父主题: 分区策略