选择表分布策略

AnalyticDB for PostgreSQL 支持两种数据在节点间的分布方式,按分布键的哈希值(HASH)分布或随机(RANDOMLY)分布。CREATE TABLE的子句DISTRIBUTED BY (column, [ ... ])指定数据按分布键的哈希值在节点(segment)间分布,子句DISTRIBUTED RANDOMLY指定数据按循环的方式均匀分配在各节点 (Segment) 间。

示例:

示例中的建表语句创建了一个哈希(Hash)分布的表,数据将按分布键的哈希值被分配到对应的 Segment 数据节点。
CREATE TABLE products (name varchar(40),
                       prod_id integer,
                       supplier_id integer)
                       DISTRIBUTED BY (prod_id);                
示例中的建表语句创建了一个随机(Randomly)分布的表,数据被循环着放置到各个 Segment 数据节点。
CREATE TABLE random_stuff (things text,
                           doodads text,
                           etc text)
                           DISTRIBUTED RANDOMLY;
对于按分布键的简单查询,包括 UPDATE/DELETE 等语句,AnalyticDB for PostgreSQL 具有按节点的分布键进行数据节点裁剪的功能,例如products表使用prod_id作为分布键,以下查询只会被发送到满足prod_id=101的segment上执行,从而极大提升该 SQL 执行性能:
select * from products where prod_id = 101;

表分布键选择原则

合理规划分布键,对表查询的性能至关重要,有以下原则需要关注:

  • 选择数据分布均匀的列或者多个列:若选择的分布列数值分布不均匀,则可能导致数据倾斜。某些Segment分区节点存储数据多(查询负载高)。根据木桶原理,时间消耗会卡在数据多的节点上。故不应选择bool类型,时间日期类型数据作为分布键。
  • 选择经常需要 JOIN 的列作为分布键,可以实现图一所示本地关联(Collocated JOIN)计算,即当JOIN键和分布键一致时,可以在 Segment分区节点内部完成JOIN。否则需要将一个表进行重分布(Redistribute motion)来实现图二所示重分布关联(Redistributed Join)或者广播其中小表(Broadcast motion)来实现图三所示广播关联(Broadcast Join)后两种方式都会有较大的网络开销
  • 尽量选择高频率出现的查询条件列作为分布键,从而可能实现按分布键做节点 segment 的裁剪。
  • 若未指定分布键,默认表的主键为分布键,若表没有主键,则默认将第一列当做分布键。
  • 分布键可以被定义为一个或多个列。例如:
    create table t1(c1 int, c2 int) distributed by (c1,c2);
  • 谨慎选择随机分布DISTRIBUTED RANDOMLY,这将使得上述本地关联,或者节点裁剪不可能实现。







表分布键的约束

  • 分布键的列不能被更新(UPDATE)。
  • 主键和唯一键必须包含分布键。例如:
    create table t1(c1 int, c2 int, primary key (c1)) distributed by (c2);
    说明 由于主键c1不包含分布键c2,所以建表语句返回失败。
    ERROR: PRIMARY KEY and DISTRIBUTED BY definitions incompatible
  • Geometry类型和用户自定义数据类型不能作为分布键。

数据倾斜检查和处理

当某些表上的查询性能差时,可以查看是否是分区键设置不合理造成了数据倾斜,例如:
create table t1(c1 int, c2 int) distributed by (c1);
您可以通过下述语句来查看表的数据倾斜情况。
select gp_segment_id,count(1) from  t1 group by 1 order by 2 desc;
 gp_segment_id | count  
---------------+--------
             2 | 131191
             0 |     72
             1 |     68
(3 rows)
如果发现某些segment上存储的数据明显多于其他segment,该表存在数据倾斜。建议选取数据分布平均的列作为分布列,比如通过ALTER TABLE命令更改C2为分布键。
alter table t1 set distributed by (c2);

表t1的分布键被改为c2,该表的数据按照c2被重新分布,数据不再倾斜。