PostgresSQL分区表不能统计下推的排查
在之前的分享中我们提到过,LXDB本质上是基于PGSQL的一个拓展,相当于更换了PG的底层数据结构。本次的实践就是基于对PG分区表无法进行统计下推的问题进行的排查和解决。
下面,开始我们本次的实践分享:
一、问题背景
近日,出于客户提出的需求,我们在LXDB中加入了分区功能。但是在功能上线之后,我们在测试拓展分区表的时候发现count(*)与group by这种分组统计并没有将计算下推到LXDB层去计算,而是将所有数据返回给PG层计算。由于数据格式的不同,在LXDB层的统计与将数据抛给PG层进行统计,两者性能相差了至少两个数量级。因此为了提高统计速度,我们需要进一步调研,为何使用Postgres的分区表后没有将count(*)与group by分组统计下沉到LXDB层中去计算。
在这里再简单介绍一下LXDB,LXDB本质是Postgres的一个拓展,相当于更换了Postgres底层的数据结构,用来解决原生PG多索引数据入库慢、更新效率较差,以及在点查、全文检索、统计分析等场景的薄弱之处。使得PG在单机情况下能做到百亿数据的毫秒级查询统计响应。
二、分区表建表
LXDB作为一款主打轻量级的数据库产品,整体的操作命令都很便捷,建表也只需要三步。
1.创建分区表
CREATE TABLE myn (
ukey text,
i1 integer,
i2 integer,
txt1 text,
txt2 text
)
PARTITION BY RANGE (i1);
2.添加分区
CREATE FOREIGN TABLE myn1 PARTITION OF myn FOR VALUES FROM (1000) TO (2000)SERVER lxdb options(store 'ios');
CREATE FOREIGN TABLE myn2 PARTITION OF myn FOR VALUES FROM (2000) TO (3000)SERVER lxdb options(store 'ios');
CREATE FOREIGN TABLE myn3 PARTITION OF myn FOR VALUES FROM (3000) TO (4000)SERVER lxdb options(store 'ios');
CREATE FOREIGN TABLE myn4 PARTITION OF myn FOR VALUES FROM (4000) TO (5000)SERVER lxdb options(store 'ios');
3.插入数据
INSERT INTO myn(ukey,i1, i2, txt1,txt2) VALUES ('1111',1500, 2, 'txt2', 'txt2');
INSERT INTO myn(ukey,i1, i2, txt1,txt2) VALUES ('1112',2500, 4, 'txt1', 'txt2');
INSERT INTO myn(ukey,i1, i2, txt1,txt2) VALUES ('1113',3500, 6, 'txt2', 'txt2');
INSERT INTO myn(ukey,i1, i2, txt1,txt2) VALUES ('1114',4500, 8, 'txt1', 'txt2');
三、问题复现与分析排查 1.问题复现
首先是执行查询:
文章图片
而后截获在LXDB里真实下发的SQL。
从截获的SQL中可以看出,系统在分组统计中暴力的将所有数据返回给了PG,结果导致了分组统计性能非常差。
文章图片
2.开始调试
首先,通过GDB调试正常分组统计的堆栈:
文章图片
【PostgresSQL分区表不能统计下推的排查】输入 gdb postgres 15627 命令后,上图红框处的 lxdbGetForeignUpperPaths 是LXDB中的分组统计的处理函数。
在这个堆栈的基础上,我们知道了函数调用堆栈是根据堆栈中的函数,一层一层的进行分析,最终发现调用堆栈差异在 create_ordinary_grouping_paths 这个方法上(见下图)。
文章图片
随后,通过pg源码分析我们在堆栈中找到的用来进行分组统计的create_ordinary_grouping_paths 这个函数。
我们可以看到分区表的执行逻辑出现了问题(见下图),PARTITIONWISE_AGGREGATE_PARTIAL 这个变量导致分区表过早的return。
文章图片
跟随这个问题,我们深入排查下 PARTITIONWISE_AGGREGATE_PARTIAL 这个变量的意思(见下图):
文章图片
但是说实话,这里我也没太理解什么意思,只好继续查看赋值的地方。发现通过如下语句可以改变这里的赋值:set enable_partitionwise_aggregate=on;
文章图片
3.继续验证,问题解决
再重新设置 set enable_partitionwise_aggregate 之后,我们再次测试一下:
文章图片
可以看到,通过调整设置,确实使得分组统计下推到LXDB层进行了计算,问题已经得到了解决。
顺便查找了下资料,了解了下partition-wise aggregation的含义:partition-wiseaggregation允许对每个分区分别执行的分区表进行分组或聚合。如果GROUP BY子句不包括分区键,则只能在每个分区的基础上执行部分聚合,并且必须稍后执行最终处理。由于partitionwise分组或聚合可能在计划期间占用大量CPU时间和内存,因此默认设置为关闭。
推荐阅读
- 2018-02-06第三天|2018-02-06第三天 不能再了,反思到位就差改变
- 良心
- 不能坚持的理由
- 第十六天(请介绍一件让你非常自豪的事情,(不能是职业类的),什么原因感到自豪。)
- 呼市首大医院温馨提示(男人有啥也不能有“qian”)
- 逃避问题并不能让问题消失
- 随笔7.21-涂改遗忘
- (If)|(If) 404 Not Found
- 小狗钱钱摘抄
- 第32天