在之前的分享中咱们提到过,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 调试失常分组统计的堆栈:
输出 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 工夫和内存,因而默认设置为敞开。