查询优化 PostgreSQL (GreenPlum)。根据排名前 5 位的结果进行分组
Posted
技术标签:
【中文标题】查询优化 PostgreSQL (GreenPlum)。根据排名前 5 位的结果进行分组【英文标题】:Query Optimalization PostgreSQL (GreenPlum). Grouping based on Top 5 Rank Results 【发布时间】:2018-08-07 12:56:47 【问题描述】:伙计们,我有这个查询来填充数据
insert into cem_summary_hourly_dly_sum_fct_20180805_x
select
trx_dt_sk_id,
month_sk_id,
sbscrptn_ek_id,
msisdn,
hours,
string_agg((case when res.seqnum <= 5 then category_name end), '|') as category_name,
string_agg((case when res.seqnum <= 5 then application_name end), '|') as application_name,
string_agg((case when res.seqnum <= 5 then browser_name end), '|') as browser_name,
string_agg((case when res.seqnum <= 5 then os_name end), '|') as os_name,
string_agg((case when res.seqnum <= 5 then volume_total_mb::character varying end), '|') as volume_mb_split,
string_agg((case when res.seqnum <= 5 then activity_sec::character varying end), '|') as active_sec_split,
sum(coalesce(volume_in, 0)) as volume_in,
sum(coalesce(volume_out, 0)) as volume_out,
sum(coalesce(volume_total_mb, 0)) as volume_total_mb,
sum(coalesce(activity_sec, 0)) as activity_sec
from (
select
trx_dt_sk_id,
month_sk_id,
sbscrptn_ek_id,
msisdn,
hours,
category_name,
application_name,
browser_name,
os_name,
rank() over (partition by hours order by sum(volume_total_mb) desc) as seqnum,
sum(coalesce(volume_in, 0)) as volume_in,
sum(coalesce(volume_out, 0)) as volume_out,
sum(coalesce(volume_total_mb, 0)) as volume_total_mb,
sum(coalesce(activity_sec, 0)) as activity_sec
from dwh.cem_summary_hourly_dly_fct_1_prt_20180805 src
group by 1,2,3,4,5,6,7,8,9 ) res
group by 1,2,3,4,5;
所以基本上我对子查询进行分组并给他们排名。然后我在排名
我使用另一种方法(在临时表上创建分组,然后检索结果)但没有任何区别。
有什么建议可以让这个查询运行得更快吗?
更新
这里是解释查询结果
"Gather Motion 64:1 (slice2; segments: 64) (cost=1902258144.94..1916188904.50 rows=30284260 width=492)"
" -> GroupAggregate (cost=1902258144.94..1916188904.50 rows=473192 width=492)"
" Group By: res.trx_dt_sk_id, res.month_sk_id, res.sbscrptn_ek_id, res.msisdn, res.hours"
" -> Sort (cost=1902258144.94..1903015251.44 rows=4731916 width=1180)"
" Sort Key: res.trx_dt_sk_id, res.month_sk_id, res.sbscrptn_ek_id, res.msisdn, res.hours"
" -> Subquery Scan res (cost=1279332227.27..1284631972.75 rows=4731916 width=1180)"
" -> Window (cost=1279332227.27..1281603546.76 rows=4731916 width=1204)"
" Partition By: src.hours"
" Order By: (sum(src.volume_total_mb))"
" -> Sort (cost=1279332227.27..1280089333.76 rows=4731916 width=1204)"
" Sort Key: src.hours, (sum(src.volume_total_mb))"
" -> Redistribute Motion 64:64 (slice1; segments: 64) (cost=391004281.95..650282943.07 rows=4731916 width=1204)"
" Hash Key: src.hours"
" -> HashAggregate (cost=391004281.95..641197665.10 rows=4731916 width=1204)"
" Group By: src.trx_dt_sk_id, src.month_sk_id, src.sbscrptn_ek_id, src.msisdn, src.hours, src.category_name, src.application_name, src.browser_name, src.os_name"
" -> Append-only Columnar Scan on cem_summary_hourly_dly_fct_1_prt_20180805 src (cost=0.00..41629947.84 rows=47319156 width=104)"
"Settings: optimizer=off"
"Optimizer status: legacy query optimizer"
一些信息:表大小约为 60GB。当前过程需要一个多小时,我们预计大约需要 15 分钟才能完成。
【问题讨论】:
发布EXPLAIN ANALYZE
结果
性能问题应该包括EXPLAIN ANALYZE
和一些关于表大小、索引、当前时间性能、期望时间等的信息。Slow
是一个相对术语,我们需要一个真实的值来比较。
@eurotrash 添加了解释结果。干杯
@JuanCarlosOropeza 嗨,我添加了解释结果和一些信息。
与您的问题无关。但是你不需要COALESCE
因为SUM
空值被忽略。 sqlfiddle.com/#!17/4b104/1
【参考方案1】:
我不能给你一个明确的答案,所以我会给你一些提示。
首先构建您的步骤查询并检查EXPLAIN ANALYZE
和每个步骤后的时间。当您发现时间增加太多时,您会更详细地研究它。
对于内部选择,您可以尝试使用包含所有这 9 个字段的复合索引来帮助该分组过程。
您还需要一个hours
的索引来帮助进行排名功能。
再次测试每一步,首先创建选择,添加字段,添加分组依据,添加聚合函数,添加 rank(),如果您发现时间增加,则添加一个索引。
【讨论】:
索引在 Greenplum 中的工作方式不同(或在某些情况下完全不同)——仅供参考。见:gpdb.docs.pivotal.io/590/admin_guide/ddl/ddl-index.html @Nicarus 在这种情况下,您不应该提供自己的答案吗?我只是试着给 OP 一些指导。以上是关于查询优化 PostgreSQL (GreenPlum)。根据排名前 5 位的结果进行分组的主要内容,如果未能解决你的问题,请参考以下文章