【发布时间】:2014-06-12 14:46:47
【问题描述】:
考虑到这个SQLFiddle 的架构,我正在尝试使用以下查询检索两个用户之间的最后一条消息:
SELECT DISTINCT ON ("user_id") *
FROM
(
(
SELECT DISTINCT ON ("user_id")
"id",
"recipient_id" AS "user_id",
"body",
"read",
"created_at"
FROM "messages"
WHERE "sender_id" = 1
ORDER BY "user_id", "created_at" DESC
)
UNION ALL
(
SELECT DISTINCT ON ("user_id")
"id",
"sender_id" AS "user_id",
"body",
"read",
"created_at"
FROM "messages"
WHERE "recipient_id" = 1
ORDER BY "user_id", "created_at" DESC
)
) AS "messages"
INNER JOIN "users" ON ("users"."id" = "messages"."user_id")
ORDER BY "user_id", "messages"."created_at" DESC
LIMIT 20;
当给定用户没有太多消息时,它按预期工作并且非常快,但是当消息数量增加并且如果消息体很大时,执行时间会变得更慢。分析执行计划会发现“瓶颈”位于这两个子查询的 ORDER BY 上,因为它必须对内存中大约 10k 行进行排序。
在为这个查询苦苦挣扎 5 小时后,我一直无法找到更快的方法来实现我想要的。我尝试在 (sender_id, created_at DESC) 和 (recipient_id, created_at DESC) 上添加索引,但显然它似乎没有帮助。
那么,我做错了什么?
谢谢
PS:这是关于执行的执行计划:http://explain.depesz.com/s/0aE
【问题讨论】:
-
您的问题措辞让我很困惑,您说的是“两个用户之间”,但您的意思似乎是说消息“由给定用户接收或发送”?
-
您希望收到最后(一条)消息,还是最后 20 条消息?
标签: sql performance postgresql