查询优化 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 位的结果进行分组的主要内容,如果未能解决你的问题,请参考以下文章

优化 PostgreSQL 中的 SQL 查询

PostgreSQL 计数查询优化

为子查询优化 Postgresql 查询

PostgreSQL代码分析,查询优化部分,process_duplicate_ors

如何优化在 postgresql 中查询这些数据?

PostgreSQL 中的优化查询