如何在分区 table 上加速服务器端聚合
How to speed up server-side aggregations over partitioned table
背景
我在 RDS 上的 Postgres 10.6 中使用 3*10^9 行的规范化分区 table 生成 Tukey 盒须图。
我开始使用连续的多个视图,包括一个聚合步骤和一个后续的离群值检测步骤。
首先,在聚合步骤中,我计算中值、25%、75%、IQR、(25% - 1.5*IQR) 下晶须和 (75% + 1.5*IQR) 上晶须。其次,在离群值检测步骤中,我在 table 中搜索胡须之外的值。
聚合
create view aggregation as
select
a.a_name,
b.b_name,
c.c_name,
percentile_cont(0.5) within group (order by d.D) as median,
etc for 75%, IQR, whiskers
from dtable as d
join atable as a on a.a_id = d.a_id
join etable as e on e.e_id = d.e_id
join ftable as f on f.f_id = e.f_id
join btable as b on b.b_id = f.b_id
join ctable as c on c.c_id = b.c_id
where (d.e_id between 3440500 and 3459500)
and (c.c_name = 'this_c_in_particular')
and (b.b_name in ('first_b', 'second_b', 'third_b'))
group by
a.a_name,
b.b_name,
c.c_name
;
请注意 dtable
被 e_id
分割
离群值检测
create view outliers as
select d.*
from dtable as d
join atable, etable, ftable, btable, ctable
join aggregation as agg on
agg.a_name = atable.a_name,
agg.b_name = btable.b_name,
agg.c_name = ctable.c_name
where d.value < agg.lower_whisker or d.value > agg.upper_whisker
;
结果
目前,使用扁平客户端 pandas 数据帧,我可以在网络传输和服务器端下采样后 10 秒内执行这些聚合。但是,在客户端,这些聚合至少需要 1 分钟才能 运行.
(EXPLAIN ANALYZE)计划可在此处获得:https://explain.depesz.com/s/0gAu
问题
- 是否有快速计算这些聚合的标准方法?
- 有没有办法让 Postgres 并行计算这些东西,每组 1 个工人?
欢迎任何见解或讨论 - 感谢阅读。
执行计划有些地方我不明白:
如果没有计划并行工作器,为什么会有 Gather
节点?从 loops
我希望有两名工人。
为什么expain.depesz.com不统计底部节点的895693次迭代(可能和我一样被上面的搞糊涂了)?
尽管如此,一些问题还是可以立即检测到的:
有严重的错误估计(725 而不是 895693 实际行!)。
您的大部分时间都花在了溢出到磁盘的排序上。
下面是您可以在不重写查询的情况下进行改进的地方:
增加work_mem
直到排序是quicksort memory
。
那应该是最大的收获了。
你不必在全球范围内增加它,你可以运行像这样:
BEGIN;
SET LOCAL work_mem = '1GB';
SELECT /* your query */;
COMMIT;
一些 table 似乎有过时的统计数据。尝试 ANALYZE
所有有问题的 table,也许这会有一些好处。
通过避免错误引导的嵌套循环连接,您可能可以多花几秒钟。也许 ANALYZE
会解决这个问题。
作为最后的手段,您可以简单地禁用该查询的嵌套循环,方法是使用我在上面为 work_mem
展示的相同技巧为一个查询设置 enable_nestloop = off
。
分区 table 上的扫描不是你的问题,所以你不必担心并行化(PostgreSQL v11 已经变得更加智能)。
如果以上都不能使查询速度足够快,可以考虑使用物化视图。然后你会得到稍微陈旧的数据,但速度很快。
背景
我在 RDS 上的 Postgres 10.6 中使用 3*10^9 行的规范化分区 table 生成 Tukey 盒须图。
我开始使用连续的多个视图,包括一个聚合步骤和一个后续的离群值检测步骤。 首先,在聚合步骤中,我计算中值、25%、75%、IQR、(25% - 1.5*IQR) 下晶须和 (75% + 1.5*IQR) 上晶须。其次,在离群值检测步骤中,我在 table 中搜索胡须之外的值。
聚合
create view aggregation as
select
a.a_name,
b.b_name,
c.c_name,
percentile_cont(0.5) within group (order by d.D) as median,
etc for 75%, IQR, whiskers
from dtable as d
join atable as a on a.a_id = d.a_id
join etable as e on e.e_id = d.e_id
join ftable as f on f.f_id = e.f_id
join btable as b on b.b_id = f.b_id
join ctable as c on c.c_id = b.c_id
where (d.e_id between 3440500 and 3459500)
and (c.c_name = 'this_c_in_particular')
and (b.b_name in ('first_b', 'second_b', 'third_b'))
group by
a.a_name,
b.b_name,
c.c_name
;
请注意 dtable
被 e_id
离群值检测
create view outliers as
select d.*
from dtable as d
join atable, etable, ftable, btable, ctable
join aggregation as agg on
agg.a_name = atable.a_name,
agg.b_name = btable.b_name,
agg.c_name = ctable.c_name
where d.value < agg.lower_whisker or d.value > agg.upper_whisker
;
结果
目前,使用扁平客户端 pandas 数据帧,我可以在网络传输和服务器端下采样后 10 秒内执行这些聚合。但是,在客户端,这些聚合至少需要 1 分钟才能 运行.
(EXPLAIN ANALYZE)计划可在此处获得:https://explain.depesz.com/s/0gAu
问题
- 是否有快速计算这些聚合的标准方法?
- 有没有办法让 Postgres 并行计算这些东西,每组 1 个工人?
欢迎任何见解或讨论 - 感谢阅读。
执行计划有些地方我不明白:
如果没有计划并行工作器,为什么会有
Gather
节点?从loops
我希望有两名工人。为什么expain.depesz.com不统计底部节点的895693次迭代(可能和我一样被上面的搞糊涂了)?
尽管如此,一些问题还是可以立即检测到的:
有严重的错误估计(725 而不是 895693 实际行!)。
您的大部分时间都花在了溢出到磁盘的排序上。
下面是您可以在不重写查询的情况下进行改进的地方:
增加
work_mem
直到排序是quicksort memory
。 那应该是最大的收获了。你不必在全球范围内增加它,你可以运行像这样:
BEGIN; SET LOCAL work_mem = '1GB'; SELECT /* your query */; COMMIT;
一些 table 似乎有过时的统计数据。尝试
ANALYZE
所有有问题的 table,也许这会有一些好处。通过避免错误引导的嵌套循环连接,您可能可以多花几秒钟。也许
ANALYZE
会解决这个问题。作为最后的手段,您可以简单地禁用该查询的嵌套循环,方法是使用我在上面为
work_mem
展示的相同技巧为一个查询设置enable_nestloop = off
。
分区 table 上的扫描不是你的问题,所以你不必担心并行化(PostgreSQL v11 已经变得更加智能)。
如果以上都不能使查询速度足够快,可以考虑使用物化视图。然后你会得到稍微陈旧的数据,但速度很快。