Greenplum表的管理实践-2 表分布策略

本文深入探讨Greenplum数据库中的表分布策略,包括哈希分布、随机分布及复制分布,详细解释如何通过分布键控制数据分布,提高查询性能,并提供实际案例演示。

5 Greenplum表的管理实践-2 表分布策略

本文主要从表的分布策略,Greenplum是一个大规模并行处理数据库,它由一个master和多个segment组成,其数据按照设定的分布策略分布于各个segment上。数据表的单个行会被分配到一个或多个segment上,但是有这么多的segment,它到底会被分到哪个或哪些segment上呢?分布策略会告诉我们。

5.1 表分布策略

在 Greenplum 5 中,有2种分布策略:

  • 哈希分布
  • 随机分布

在 Greenplum 6 中,添加了另一个策略:

  • 哈希分布
  • 随机分布
  • 复制分布

哈希分布

要使用这一策略,需要在创建表使用 “DISTRIBUTED BY(column,[…])” 子句。

散列算法使分布键将每一行分配给特定 segment。相同值的键将始终散列到同一个 segment。选择唯一的分布键(例如Primary Key)将确保较均匀的数据分布。哈希分布是表的默认分布策略。

如果创建表时未提供 DISTRIBUTED 子句,则将 PRIMARY KEY(如果表真的有的话)或表的第一个合格列用作分布键。什么类型的列是合格列呢?几何类型或用户自定义数据类型的列不能用作 Greenplum 分布键列。如果表中没有合格的列,则退化为随机分布策略。

但是,如果未提供 DISTRIBUTED 子句,Greenplum 最后会选择哪种分布策略还会受其它因素的影响,例如:GUC gp_create_table_random_default_distribution 和当时使用的优化器(optimizer)也将影响最终决定。因此,请千万不要忘记在 CREATE TABLE 时添加 DISTRIBUTED BY 子句

Note: 如果创建表时没有指定DISTRIBUTED BY,Greenplum数据库服务器配置参数

gp_create_table_random_default_distribution

[gpadmin@mdw ~]$ gpconfig --show gp_create_table_random_default_distribution
Values on all segments are consistent
GUC          : gp_create_table_random_default_distribution
Master  value: off
Segment value: off
[gpadmin@mdw ~]$

随机分布

要使用这一策略,需要在创建表使用 “DISTRIBUTED RANDOMLY” 子句。

随机分布会将数据行按到来顺序依次循环发送到各个 segment 上。与哈希分布策略不同,具有相同值的数据行不一定位于同一个 segment 上。虽然随机分布确保了数据的平均分布,但只要有可能,应该尽量选择哈希分布策略,哈希分布的性能更加优良。

复制分布

这种分布策略是 GPDB 6 的新增特性。要使用这一策略,需要在创建表使用 “DISTRIBUTED REPLICATED” 子句。

Greenplum 数据库将每行数据分配到每个 segment上。这种分布策略下,表数据将均匀分布,因为每个 segment 都存储着同样的数据行。当您需要在 segment 上执行用户自定义的函数且这些函数需要访问表中的所有行时,就需要用到复制分布策略。或者当有大表与小表 join,把足够小的表指定为 replicated 也可能提升性能。

请注意,有一个例外:catalog 表没有分布策略

关于3项策略的摘要:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IhPKnWSd-1588921554857)(D:\SYBASE&informix&DB2\Greenplum\4 学习笔记\数据库管理\5 Greenplum表的管理实践-2.assets\3baead233c6f42a4bdc7f48d93c272cc.jpg)]

控制表的分布策略。

更多有关该参数的信息,请见Greenplum数据库参考指南的“服务器配置参数”部分。

在决定表分布策略时,请考虑以下几点。

  • 均匀数据分布 — 为了最好的性能,所有的Segment应该包含等量的数据。如果数据不平衡或者倾斜,具有更多数据的Segment就必须做更多工作来执行它那一部分的查询处理。 请选择对于每一个记录都唯一的分布键,例如主键。
  • 本地和分布式操作 — 本地操作比分布式操作更快。在Segment层面上,如果与连接、排序或者聚集操作相关的工作在本地完成,查询处理是最快的。在系统层面完成的工作要求在Segment之间分布元组,其效率会低些。当表共享一个共同的分布键时,在它们共享的分布键列上的连接或者排序工作会在本地完成。对于随机分布策略来说,本地连接操作就行不通了。
  • 均匀查询处理 — 为了最好的性能,所有的Segment应该处理等量的查询负载。如果一个表的数据分布策略与查询谓词匹配不好,查询负载可能会倾斜。例如,假定一个销售事务表按照客户ID列(分布键)分布。如果查询中的谓词引用了一个单一的客户ID,该查询处理工作会被集中在一个Segment上。
选择法则:

1)尽量选择经常需要 JOIN 的列

当关联键和分布键均一致时,可以在 Segment 中完成 JOIN,不需要重分布或者广播小表。

当关联键和分布键不一致时,则需要重分布不一致的表或者广播小表,带来额外的开销。

2)尽量选择分布均匀的列或者多列

若选择的分布列值分布不均匀,则可能导致数据倾斜。某些 Segment 非常大(压力大),某些 Segment 非常小。根据木桶原理,时间消耗会卡在数据多的节点上。

3)尽量选择高并发查询的条件列(指该查询条件产生的中间结果集小的,如果中间结果集很大,那就让所有节点都来参与运算更好,因此不选)

如果数据经常被高并发的键值或离散查询,可以将查询条件的列作为分布列,这样不需要连接到所有的 Segment 去查,可以大大提高并发能力。

4)不要轻易使用随机分布

复制表分布策略(DISTRIBUTED REPLICATED)应该在小表上使用。 将大表数据复制到每个节点上无论在存储还是维护上都是有代价的。 复制表最基本的用例是:

  • 删除用户定义的函数可以对节点执行的操作的限制
  • 频繁使用的表不需要广播到所有节点可以提高查询性能。
声明分布键

CREATE TABLE命令的可选子句DISTRIBUTED BY, DISTRIBUTED RANDOMLY和DISTRIBUTED REPLICATED决定了表的分布策略。默认的哈希分布策略使用PRIMARY KEY(如果有的话)或表的第一列作为分布键。几何信息列或用户自定义数据类型的列是不能作为Greenplum数据库分布列的。 如果找不到合适的哈希分布的列,Greenplum数据库就选择随机分布策略。

复制表没有分布列,因为每行都分布在Greenplum数据库所有节点上。

为了保证哈希分布数据的均匀分布,最好选一个唯一键作为分布列。如果找不到,则选择DISTRIBUTED RANDOMLY。例如:

=> CREATE TABLE products
                        (name varchar(40),
                         prod_id integer,
                         supplier_id integer)
             DISTRIBUTED BY (prod_id);
=> CREATE TABLE random_stuff
                        (things text,
                         doodads text,
                         etc text)
             DISTRIBUTED RANDOMLY;

Important: 主键总是表的分布列。如果没有主键,但是有唯一索引存在,则选择它为分布键。

自定义分布键哈希函数

用于哈希分布策略的哈希函数由列的数据类型的哈希运算符类定义。由于默认的Greenplum数据库使用数据类型的默认哈希运算符类,因此用于哈希连接和哈希聚合的运算符类相同,适用于大多数用例。 但是,您可以在DISTRIBUTED BY子句中声明非默认的哈希运算符类。

使用自定义哈希运算符类可以用于支持与默认相等运算符(=)不同的运算符上的共存连接。

自定义哈希操作符类用例

此示例为整数数据类型创建自定义哈希运算符类,该类用于提高查询性能。运算符类比较整数的绝对值。

创建一个函数和一个等于运算符,如果两个整数的绝对值相等,则返回true。

CREATE FUNCTION abseq(int, int) RETURNS BOOL AS
$$
  begin return abs($1) = abs($2); end;
$$ LANGUAGE plpgsql STRICT IMMUTABLE;

CREATE OPERATOR |=| (
  PROCEDURE = abseq,
  LEFTARG = int,
  RIGHTARG = int,
  COMMUTATOR = |=|,
  hashes, merges);

现在,创建一个使用运算符的哈希函数和运算符类。

CREATE FUNCTION abshashfunc(int) RETURNS int AS
$$
  begin return hashint(abs($1)); end;
$$ LANGUAGE plpgsql STRICT IMMUTABLE;

CREATE OPERATOR CLASS abs_int_hash_ops FOR TYPE int4
  USING hash AS
  OPERATOR 1 |=|,
  FUNCTION 1 abshashfunc(int);

并且,为它们创建小于和大于运算符和B树运算符类。我们的查询不需要它们,但是Greenplum数据库的Postgres查询优化器必须依赖它们做连接的co-location。

CREATE FUNCTION abslt(int, int) RETURNS BOOL AS
$$
  begin return abs($1) < abs($2); end;
$$ LANGUAGE plpgsql STRICT IMMUTABLE;

CREATE OPERATOR |<| (
  PROCEDURE = abslt,
  LEFTARG = int,
  RIGHTARG = int);

CREATE FUNCTION absgt(int, int) RETURNS BOOL AS
$$
  be
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值