【发布时间】:2016-05-13 08:47:19
【问题描述】:
我有两个表:conversations 和 messages,每个对话都有很多消息
Message: (id, conversation_id, text, inserted_at, ...)
Conversation: (id, user_id ...)
我想显示一个对话列表,并为每个对话显示最近添加的消息的文本和时间戳。我还想根据最近添加的消息(最新消息在顶部)的时间戳对这些对话进行降序排序
目前,我使用 MAX 函数计算这些(以下是我的 ORM 生成的查询)
SELECT c0."id", MAX(m5."inserted_at"),
(SELECT data->>'text' FROM messages
WHERE conversation_id = c0."id" AND type = 'message'
ORDER BY inserted_at DESC
LIMIT 1)
, c4."unread_count", v6."name", v6."id", (SELECT array(
SELECT type FROM tags
WHERE conversation_id = c0."id")) FROM "conversations" AS c0 INNER JOIN "tags" AS t1 ON t1."conversation_id" = c0."id" LEFT OUTER JOIN "messages" AS m2 ON m2."conversation_id" = c0."id" INNER JOIN "conversation_users" AS c7 ON c7."conversation_id" = c0."id" INNER JOIN "users" AS u3 ON c7."user_id" = u3."id" INNER JOIN "conversation_users" AS c4 ON c4."conversation_id" = c0."id" INNER JOIN "messages" AS m5 ON m5."conversation_id" = c0."id" INNER JOIN "visitors" AS v6 ON v6."id" = c0."visitor_id" WHERE (t1."type" = $1) AND (NOT (m2."visitor_id" IS NULL)) AND (u3."id" = $2) AND (c4."user_id" = $3) GROUP BY c0."id", c4."unread_count", v6."id", v6."name" ORDER BY MAX(m5."inserted_at") DESC LIMIT 10
我的问题是,每次添加新消息时,将这些值非规范化并将它们直接保存在对话记录中是否更有意义?
在 has_many 关联上执行 3 MAX 似乎非常昂贵(仅 3000 条消息需要 600 毫秒)
【问题讨论】:
-
你有合适的索引吗?旁注:NOSQL 数据库可能更适合这种用例。
-
我对所有外键都有标准索引,并且我还在
messages表上索引了inserted_at 字段。 -
我希望
messages中inserted_at上的索引在索引中具有对话ID。 -
是的,我在两者上都有一个复合索引
-
你能发布解释/执行计划吗?
标签: sql relational-database database-optimization