摘要: 标签 PostgreSQL , Greenplum , varbitx , roaring bitmap , pilosa , varbit , hll , 多阶段聚合 背景 roaring bitmap是一个压缩比很高同时性能不错的BIT库,被广泛使用(例如Greenplum, ES, InfluxDB.
标签
PostgreSQL , Greenplum , varbitx , roaring bitmap , pilosa , varbit , hll , 多阶段聚合
背景
roaring bitmap是一个压缩比很高同时性能不错的BIT库,被广泛使用(例如Greenplum, ES, InfluxDB……):
Roaring bitmaps are compressed bitmaps which tend to outperform conventional compressed bitmaps such as WAH, EWAH or Concise. They are used by several major systems such as Apache Lucene and derivative systems such as Solr and Elasticsearch, Metamarkets’ Druid, LinkedIn Pinot, Netflix Atlas, Apache Spark, OpenSearchServer, Cloud Torrent, Whoosh, InfluxDB, Pilosa, Bleve, Microsoft Visual Studio Team Services (VSTS), and eBay’s Apache Kylin.
《Roaring Bitmap - A better compressed bitset》
https://github.com/RoaringBitmap/CRoaring
在PostgreSQL中内置了varbit的数据类型,阿里云在其基础上扩展了对varbit的操作符:
《阿里云RDS for PostgreSQL varbitx插件与实时画像应用场景介绍》
是的阿里云RDS PG支持以更低的成本、更高的性能支持海量画像的实时计算:
《阿里云RDS PostgreSQL varbitx实践 - 流式标签 (阅后即焚流式批量计算) - 万亿级,任意标签圈人,毫秒响应》
《基于 阿里云 RDS PostgreSQL 打造实时用户画像推荐系统(varbitx)》
《惊天性能!单RDS PostgreSQL实例 支撑 2000亿 - 实时标签透视案例》
对于Greenplum,同样有社区的朋友贡献的插件,让Greenplum可以支持roaringbitmap类型。
开源代码如下(感谢贡献代码的小伙伴):
https://github.com/zeromax007/gpdb-roaringbitmap
(目前这个版本没有将聚合做到计算节点,而是走了gather motion再聚合的方式,聚合性能不佳)。
postgres=# explain select rb_cardinality(rb_and_agg(bitmap)) from t1;
QUERY PLAN
----------------------------------------------------------------------------------------
Aggregate (cost=1.05..1.07 rows=1 width=4)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..1.05 rows=1 width=1254608)
-> Seq Scan on t1 (cost=0.00..1.01 rows=1 width=1254608)
(3 rows)
Time: 0.727 ms
建议有兴趣的同学可以改进一下 roaringbitmap for Greenplum 聚合代码,改成多阶段聚合,让聚合先在计算节点做。
自定义分布式聚合的方法参考如下:
《PostgreSQL 10 自定义并行计算聚合函数的原理与实践》
《Postgres-XC customized aggregate introduction》
《PostgreSQL aggregate function customize》
《Greenplum 最佳实践 - 估值插件hll的使用(以及hll分式聚合函数优化)》
接下来简单介绍一下roaringbitmap的安装与功能点。
安装
1、首先你需要安装好greenplum。
2、然后你需要下载gpdb-roaringbitmap
git clone https://github.com/zeromax007/gpdb-roaringbitmap
3、编译gpdb-roaringbitmap
If $GPHOME is /usr/local/gpdb .
gcc -march=native -O3 -std=c11 -Wall -Wpointer-arith -Wendif-labels -Wformat-security \
-fno-strict-aliasing -fwrapv -fexcess-precision=standard -fno-aggressive-loop-optimizations \
-Wno-unused-but-set-variable -Wno-address -fpic -D_GNU_SOURCE \
-I/usr/local/gpdb/include/postgresql/server \
-I/usr/local/gpdb/include/postgresql/internal \
-c -o roaringbitmap.o roaringbitmap.c
或如下,主要看你的头文件在哪里
gcc -march=native -O3 -std=c11 -Wall -Wpointer-arith -Wendif-labels -Wformat-security \
-fno-strict-aliasing -fwrapv -fexcess-precision=standard -fno-aggressive-loop-optimizations \
-Wno-unused-but-set-variable -Wno-address -fpic -D_GNU_SOURCE \
-I/usr/local/gpdb/include/server \
-I/usr/local/gpdb/include/internal \
-c -o roaringbitmap.o roaringbitmap.c
gcc -O3 -std=gnu99 -Wall -Wpointer-arith -Wendif-labels -Wformat-security \
-fno-strict-aliasing -fwrapv -fexcess-precision=standard -fno-aggressive-loop-optimizations \
-Wno-unused-but-set-variable -Wno-address -fpic -shared --enable-new-dtags \
-o roaringbitmap.so roaringbitmap.o
4、将so文件拷贝到所有gpdb节点(所有master, slave, segment, mirror等)的软件目录对应的lib目录中.
cp ./roaringbitmap.so /usr/local/gpdb/lib/postgresql/
5、在MASTER节点,连接到需要使用roaringbitmap的DB中,执行如下SQL,安装对应的类型,操作符,函数等。
psql -f ./roaringbitmap.sql
使用DEMO
1、建表,使用roaringbitmap数据类型
CREATE TABLE t1 (id integer, bitmap roaringbitmap);
2、使用rb_build生成roaringbitmap的数据(输入为数组,输出为roaringbitmap。含义:数组位置对应的bit值设置为1)。
INSERT INTO t1 SELECT 1,RB_BUILD(ARRAY[1,2,3,4,5,6,7,8,9,200]);
– 将输入的多条记录的值对应位置的BIT值设置为1,最后聚合为一个
roaringbitmap
INSERT INTO t1 SELECT 2,RB_BUILD_AGG(e) FROM GENERATE_SERIES(1,100) e;
3、两个roaringbitmap的BIT计算(OR, AND, XOR, ANDNOT)。andnot表示第一个参数与第二个参数的NOT进行AND操作,等同于andnot(c1,c2)==and(c1, not(c2))
SELECT RB_OR(a.bitmap,b.bitmap) FORM (SELECT bitmap FROM t1 WHERE id = 1) AS a, (SELECT bitmap FROM t1 WHERE id = 2) AS b;
4、一些聚合操作,并生成新的roaringbitmap (OR, AND, XOR, BUILD)
SELECT RB_OR_AGG(bitmap) FROM t1;
SELECT RB_AND_AGG(bitmap) FORM t1;
SELECT RB_XOR_AGG(bitmap) FROM t1;
SELECT RB_BUILD_AGG(e) FROM GENERATE_SERIES(1,100) e;
5、Cardinality,即roaringbitmap中包含多少个位置为1的BIT位。
SELECT RB_CARDINALITY(bitmap) FROM t1;
6、从roaringbitmap返回位置为1的BIT的下标(位置值)。
SELECT RB_ITERATE(bitmap) FROM t1 WHERE id = 1;
postgres=# select rb_iterate(rb_build('{1,4,100}'));
rb_iterate
------------
1
4
100
(3 rows)
7、一些bit设置操作
postgres=# select rb_iterate(rb_flip(rb_build('{1,2,3,100,4,5}'),7,10));
rb_iterate
------------
1
2
3
4
5
7
8
9
100
(9 rows)
内置计算函数说明
小结
gpdb-roaringbitmap是一个很好的插件,可以帮助用户高效的实现多组标签的人群圈选。
目前需要实现prefunc来支持多阶段聚合,否则只能gather到master去聚合。文中有例子。
扫描二维码获取更多消息: