【问题标题】:Postgres: Optimize a huge GROUP BYPostgres:优化一个巨大的 GROUP BY
【发布时间】:2019-06-05 09:59:35
【问题描述】:

我有这样一张桌子:

CREATE TABLE values (first_id varchar(26), sec_id int, mode varchar(6), external1_id varchar(23), external2_id varchar(26), x int, y int);

可能有多个值具有相同的 first_id,我的目标是将每个 first_id 的所有相关行展平(转换为 json)到另一个表中。

我是这样做的:

INSERT INTO othervalues(first_id, results)
  SELECT first_id, json_agg(values) AS results FROM values GROUP BY first_id;

在结果列中,我有一个包含所有行的 json 数组,以后可以照原样使用。

我的问题是这非常慢,有一个巨大的表:值大约 100 000 000 行,这会减慢我的计算机(我实际上是在本地测试)直到它死掉(这是一个 Ubuntu)。

使用 EXPLAIN 我注意到使用了 GroupPartitioner,我补充说:

SET work_mem = '1GB';

现在它使用 HashPartitioner,但这仍然会杀死我的计算机。一个解释给了我:

Insert on othervalues  (cost=2537311.89..2537316.89 rows=200 width=64)
  ->  Subquery Scan on "*SELECT*"  (cost=2537311.89..2537316.89 rows=200 width=64)
        ->  HashAggregate  (cost=2537311.89..2537314.39 rows=200 width=206)
              ->  Seq Scan on values  (cost=0.00..2251654.26 rows=57131526 width=206)

知道如何优化它吗?

【问题讨论】:

  • 等等...values 既是列的名称又是表的?您的插入查询中有错字吗?
  • 你有first_id的索引吗?
  • @stickybit 索引可能对json_agg 的调用没有多大帮助,这可能必须触及组中的每个值(阅读:扫描)。
  • @TimBiegeleisen:啊错过了,values 不是专栏。
  • @TimBiegeleisen 这是一个整行参考。

标签: postgresql optimization query-optimization aggregation


【解决方案1】:

我最终使用的解决方案是将 GROUP BY 拆分为多个:

首先,我创建一个临时表,其中包含我要分组的内容的唯一 ID。这允许仅获得部分结果 - 就像使用 OFFSET 和 LIMIT - 但是这些结果集可能非常慢(大偏移意味着执行树将浏览第一个结果):

CREATE TEMP TABLE tempids AS SELECT ROW_NUMBER() OVER (ORDER BY theid), theid FROM (SELECT DISTINCT theid FROM sourcetable) sourcetable;

然后在 WHILE 循环中:

DO $$DECLARE
  r record;
  i INTEGER := 0;
  step INTEGER := 500000;
  size INTEGER := (SELECT COUNT(*) FROM tempids);
  BEGIN
  WHILE i <= size
      LOOP
        INSERT INTO target(theid, theresult)
        SELECT ... 
        WHERE tempids > i AND tempids < i + step
       GROUP BY tempids.theid;

这看起来像通常的编码,这不是很好的 sql,但它有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    相关资源
    最近更新 更多