原生功能
原生的Greenplum内核不带有RoaringBitmap插件,开源社区实现了该功能,从而使得Greenplum可以支持RoaringBitmap类型。但该版本对于多阶段的聚合,并没有将聚合做到计算节点,而是实现为在主节点gathermotion再聚合,从而导致聚合性能不佳。
从SQL执行计划也可以看出,原生方式下的RoaringBitmap实现,采用的是主节点上的单阶段聚合,这也成为了我们可以进行性能优化的一个方面。
我们针对聚合操作进行了优化并改进,使得聚合操作采用多阶段聚合的方式实现,进一步提升RoaringBitmap在阿里云RDS实际业务中的性能。改进后的具体实现逻辑如下:
我们通过在从节点完成一阶段聚合操作,再由主节点完成二阶段聚合,从而充分利用从节点自身计算性能,采用多阶段方式,提高聚合操作性能。 改进后的执行计划为多阶段方式执行。
QUERY PLAN
-----------------------------------------------------------------------------------
Aggregate (cost=1.08..1.09 rows=1 width=32)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=1.01..1.06 rows=1 width=32)
-> Aggregate (cost=1.01..1.02 rows=1 width=32)
-> Seq Scan on t1 (cost=0.00..1.01 rows=1 width=40)
(4 rows)
性能测试1
- 表结构
- 测试结果
- 结果分析
主节点个数为1,从节点个数为3,相较于不采用多阶段聚合方式,性能提升基本在2-3倍,其中rb_and_agg原生环境下在主节点聚合所有数据,优化后效果明显。
为进一步说明ARRAY长度的大小不会使得改进后的方案性能降低,进行了第二轮性能测试。
- 表结构
CREATE TABLE t1 (id integer, bitmap roaringbitmap);
INSERT INTO t1 SELECT GENERATE_SERIES(1,1000000),RB_BUILD(ARRAY(SELECT *FROM GENERATE_SERIES(1,10000)));
- 测试结果
- 结果分析
主节点个数为1,从节点个数为3,相较于不采用多阶段聚合方式,性能提升基本在2-3倍。其中rb_and_agg与rb_and_cardinality_agg执行时间超过10分钟,为方便构建测试结果图,取10w毫秒。
部署方法
创建插件
创建测试表
postgres=# create table t1 (id integer, bitmap roaringbitmap);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'id' as the Greenplum Database data distribution key for this table.
CREATE TABLE
插入测试数据
postgres=# select rb_or_agg(bitmap) from t1;
rb_or_agg
--------------------------------------------------------------------------------------------------------------------------------------------
:0\000\000\001\000\000\000\000\000\011\000\020\000\000\000\001\000\002\000\003\000\004\000\005\000\006\000\007\000\010\000\011\000\310\000
(1 row)
rb_or_agg
--------------------------------------------------------------------------------------------------------------------------------------------
:0\000\000\001\000\000\000\000\000\011\000\020\000\000\000\001\000\002\000\003\000\004\000\005\000\006\000\007\000\010\000\011\000\310\000
(1 row)
postgres=# select rb_and_agg(bitmap) from t1;
rb_and_agg
--------------------------------------------------------------------------------------------------------------------------------------------
:0\000\000\001\000\000\000\000\000\011\000\020\000\000\000\001\000\002\000\003\000\004\000\005\000\006\000\007\000\010\000\011\000\310\000
(1 row)
postgres=# select rb_xor_agg(bitmap) from t1;
rb_xor_agg
--------------------------------------------------------------------------------------------------------------------------------------------
:0\000\000\001\000\000\000\000\000\011\000\020\000\000\000\001\000\002\000\003\000\004\000\005\000\006\000\007\000\010\000\011\000\310\000
postgres=# select rb_build_agg(id) from t1;
rb_build_agg
--------------------------------------------------------------------
(1 row)
postgres=# select rb_or_cardinality_agg(bitmap) from t1;
rb_or_cardinality_agg
-----------------------
10
(1 row)
postgres=# select rb_and_cardinality_agg(bitmap) from t1;
rb_and_cardinality_agg
------------------------
10
(1 row)
postgres=# select rb_xor_cardinality_agg(bitmap) from t1;
rb_xor_cardinality_agg
------------------------
10
我们将Greenplum原生RoaringBitmap插件进行了优化,增加了对聚合操作的多阶段执行处理,提升了RoaringBitmap多阶段聚合操作的执行性能。