如何有效地按子查询的结果排序?

时间:2019-10-23 13:11:25

标签: sql postgresql performance indexing sql-order-by

假设我有一个类似Stackoverflow的网站,人们可以对其进行回复,并且我希望有一个界面可以按回复数对帖子进行排序

这最终将具有无限的滚动分页,因此一次显示10个结果。

这是一个查询示例:

SELECT *, (SELECT COUNT(*) 
           FROM post_reply pr 
           WHERE pr.convo_id = post.convo_id) as replies 
FROM post 
ORDER BY replies 
LIMIT 10;

这有效,但是速度太慢。我有成千上万的帖子,这导致查询需要30多个秒才能完成。

索引可以提高速度,但是我不知道如何在子查询上实现索引。

实体化视图也可以工作,但是每次有人回复帖子时更新实体化视图似乎也太慢了。

这个问题有很好的解决方法吗?

2 个答案:

答案 0 :(得分:1)

您无法真正加快此查询的速度。

您可以更改数据模型,并使用大量基础结构来获得更快的排序。这个想法是:

  1. 将列post_reply_count添加到posts表中。
  2. 在此列上添加索引。
  3. 使用触发器使此列保持最新状态-+ 1的{​​{1}},insert的{​​{1}}。以及适合- 1的一切。
  4. 在查询中使用此列。

这增加了开销。但是,如果您确实需要对此查询进行快速响应,则可能别无选择。

答案 1 :(得分:1)

您可以更改查询顺序,并首先通过回复计数生成帖子列表,然后获取post列。这应该使用主键(我假设post.convo_id是主键),并且可能会更快,但我不保证会这样。

SELECT post.*, sub.replies
  FROM (SELECT pr.convo_id, COUNT(*) AS replies
          FROM post_reply pr
         GROUP BY pr.convo_id
         ORDER BY replies --maybe DESC if you want top reply count first
         LIMIT 10
       ) AS sub
  JOIN post USING(convo_id);