【问题标题】:PostgreSQL: query with join and group by is taking too longPostgreSQL:使用 join 和 group by 查询花费的时间太长
【发布时间】:2020-01-31 11:23:52
【问题描述】:

我有两张表,如下所示:

table_1:

-----------------------------------
| ID  |  customer_id  |   city    |
-----------------------------------
| 0   |  E100         |  Sydney   |
-----------------------------------
| 1   |  E200         |  Toronto  | 
-----------------------------------
| 2   |  E300         |  New York |
-----------------------------------

table_2:

----------------------------------------------
| customer_id  |    timestamp   |   receipt  |
----------------------------------------------
|    E200      |  '2019-03-25'  |    200$    | 
----------------------------------------------
|    E300      |  '2019-03-26'  |    300$    |
----------------------------------------------
|    E300      |  '2019-03-26'  |    100$    |
----------------------------------------------
|    E100      |  '2019-03-27'  |     50$    | 
----------------------------------------------
|    E100      |  '2019-03-28'  |     50$    |
----------------------------------------------
|    E100      |  '2019-03-29'  |     50$    |
----------------------------------------------

我想要做的是总结每个不同 customer_id 的所有收据。 结果表应如下所示:

----------------------------------------------
| customer_id |    city    |   sum(receipt)  |
----------------------------------------------
|    E100     |  Sydney    |      150$       |
----------------------------------------------
|    E200     |  Toronto   |      200$       | 
----------------------------------------------
|    E300     |  New York  |      400$       |
----------------------------------------------

为了实现这一点,我使用以下 PostgreSQL 查询:

SELECT a.customer_id, a.city, SUM(b.receipt) 
FROM public.table_1 a 
INNER JOIN public.table_2 b
   ON a.customer_id = b.customer_id
   WHERE b.timestamp > '2019-03-25 00:00:00' 
   AND b.timestamp < '2019-04-01 00:00:00' 
GROUP BY a.customer_id, a.city

但是,由于 table_2 有超过 300mio 行,而 table_1 有 129 行, 查询花费的时间太长(我不知道究竟需要多长时间 -> EXPLAIN ANALYZE 对此查询也没有完成)。我猜 INNER JOIN 是这里的瓶颈(如果我错了请纠正我)? 但我确实知道该查询正在做正确的事情,因为我已经尝试过滤一天(而不是一周)。

我的问题是如何加快这个查询。我已经考虑过添加这样的索引:

CREATE INDEX table_2_index ON table_2(customer_id, timestamp)

但是这个查询也需要很长时间。

有什么建议吗?

【问题讨论】:

  • 如果EXPLAIN ANALYZE 花费的时间太长,您可以使用简单的EXPLAIN 代替,它的用处要小得多,但它仍然可以显示数据库的想法。之后您可以手动验证步骤(即SELECT COUNT(*) FROM table WHERE ...
  • 正如下面的答案中提到的,最终“加入然后聚合”可能会比“聚合然后加入”模式慢。在您的情况下,表public.table_2 应该是“主”,因此首先您应该优化select customer_id, sum(receipt) from table_2 where timestamp &gt; '2019-03-25 00:00:00' and timestamp &lt; '2019-04-01 00:00:00' group by customer_id 之类的查询,然后将其与table_1 连接起来(我相信customer_id 与@987654333 对具有相同的唯一性@)

标签: sql postgresql performance join indexing


【解决方案1】:

尝试先聚合,再加入:

SELECT a.customer_id, a.city, b.receipt_sum
FROM public.table_1 a 
 JOIN (
   SELECT t2.customer_id, sum(t2.receipt) as receipt_sum
   FROM public.table_2 t2
   WHERE t2.timestamp > '2019-03-25 00:00:00' 
     AND t2.timestamp < '2019-04-01 00:00:00' 
   GROUP BY t2.customer_id
 ) b ON a.customer_id = b.customer_id

【讨论】:

    【解决方案2】:

    让我们在加入之前先尝试过滤您的 table_2 表。

    SELECT a.customer_id, a.city, SUM(b.receipt) 
    FROM public.table_1 a
    INNER JOIN 
    (SELECT receipt, customer_id FROM public.table_2 
        WHERE timestamp > '2019-03-25 00:00:00' 
        AND timestamp < '2019-04-01 00:00:00') b ON a.customer_id = b.customer_id
    GROUP BY a.customer_id, a.city
    

    【讨论】:

    • 现在需要 1 分钟。非常感谢!
    • 有没有办法在一个查询中为另一个时间间隔添加另一列receipt_sums?
    • 复制整个内连接INNER JOIN (SELECT receipt, customer_id FROM public.table_2 WHERE timestamp &gt; '2019-03-25 00:00:00' AND timestamp &lt; '2019-04-01 00:00:00') c ON a.customer_id = c.customer_id,然后添加新列SUM(c.receipt)
    猜你喜欢
    • 1970-01-01
    • 2021-01-07
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多