【问题标题】:Postgres join on min(*) + group by super slowPostgres join on min(*) + group by super slow
【发布时间】:2020-08-28 01:14:00
【问题描述】:

这是我的查询的样子:

SELECT DISTINCT user.id AS user_id, messaged_date
FROM users
         JOIN (
           SELECT MIN(message_date) AS messaged_date,
                user_id
           FROM messages
           GROUP BY user_id
     ) messages_join ON user.id = messages_join.user_id
WHERE (user.client_id IN ('1234')
    AND user.status IN ('statusA')
);
  1. messages 表有两列 -> user_idmessaged_date。我有一个索引和多列索引(user_id, messaged_data asc nulls last)
  2. messages 桌子很大。大小约为 50Gb。
  3. 查询需要很长时间(5 分钟以上)才能运行。
  4. 如果我删除连接,它会在 1 秒内返回。
  5. 我想要每个user_id 一行

如何使查询执行得更快?显然,min 加上 group_by 的加入是原因。 (EXPLAIN 证实了这一点。)

我尝试了loose index scan, aka a "skip scan",它本身性能很好,但在加入它的结果时没有帮助。

【问题讨论】:

  • 你想做什么?
  • 获取用户收到消息的最早日期,在 client_idstatus 上过滤
  • 这不是您的查询所做的......
  • 我的错,我在选择子句中添加了缺少的messaged_date

标签: sql postgresql query-optimization amazon-aurora


【解决方案1】:

这解决了问题的原始版本。

子查询很奇怪。看起来你只是想要exists:

SELECT u.id AS user_id
FROM users u
WHERE u.client_id IN ('1234') AND
      u.status IN ('statusA') AND
      EXISTS (SELECT 1
              FROM messages m
              WHERE m.user_id = u.id
             );

这可以利用messages(user_id) 上的索引。

【讨论】:

  • 这不会将消息折叠到最早的消息,min(messaged_date) 会这样做。
  • @ritratt 。 . .您没有使用最早的日期。
  • 哎呀,我的错。我将列添加到选择中。
【解决方案2】:

也许你想要这个:

SELECT DISTINCT ON (users.id)
       users.id AS user_id,
       messages.message_date AS messaged
FROM users
   JOIN messages
      ON users.id = messages.user_id
WHERE users.client_id = '1234'
  AND users.status = 'statusA'
ORDER BY users.id, message.message_date;

可以加快查询速度的索引:

CREATE INDEX ON users (client_id, status);
CREATE INDEX ON messages (user_id);

【讨论】:

  • 这看起来很有希望,但仍然需要很长时间
  • 我修复了答案中的一些错误并添加了两个索引建议。
  • 我已经有了messages (user_id) 索引。我还添加了users (client_id, status) 索引。但仍然需要 5 多分钟。
  • 除非您将EXPLAIN (ANALYZE, BUFFERS) 输出添加到问题中,否则您无法获得更多信息。
猜你喜欢
  • 1970-01-01
  • 2017-12-07
  • 2011-09-15
  • 2010-10-21
  • 2019-03-21
  • 2022-01-08
  • 2013-04-06
  • 1970-01-01
  • 2012-07-25
相关资源
最近更新 更多