优化查询sql for messenger

时间:2013-08-05 16:03:08

标签: mysql sql postgresql

我有一个包含5百万行的消息表,我想检索两个用户对话的最后10行

+---------------------------------------------------------------+
|                          messages                             |
+---------------------------------------------------------------+
| message_id | id_sender | id_dest |  subject | message | time  |
+---------------------------------------------------------------+

这是我如何优化它的查询?

SELECT *
FROM 
    (SELECT message
    FROM messages 
    WHERE ( id_sender = id1 AND id_dest = id2 ) or
          ( id_dest = id1 AND id_sender = id2 )
    ORDER BY message_id DESC
    LIMIT 10) AS ttbl
ORDER BY message_id ASC

谢谢!

我有id_sender id_dest和message_1d

的索引

更新

4 个答案:

答案 0 :(得分:3)

关于优化的第一个注意事项,它比如何优化它更多参与?

其次,一些想法:

  • 如果没有必要,请不要使用SELECT *。只需带回所需的字段。
  • 这构建了第一个。建立覆盖指数。这意味着如果在任何地方的查询中使用字段a, b, c,那么您可以在表上的a, b, c上构建索引。这将允许数据库读取索引页面,而不必从数据页面中搜索,加载和读取。

答案 1 :(得分:1)

这是您的查询:

SELECT *
FROM (SELECT *
      FROM messages 
      WHERE (id_sender = id1 AND id_dest = id2) or
            (id_dest = id1 AND id_sender = id2)
      ORDER BY message_id DESC
      LIMIT 10
     ) ttbl
ORDER BY message_id ASC;

message(id_sender, id_dest, message_id)上创建索引。这将允许使用索引来满足内部查询。

我不担心* - 在操作查询中使用*是不好的做法,因为基础表可能会发生变化。为此,您选择了10条记录。引擎必须查找10条记录以获取所有字段并对它们进行排序(第一种类型应由索引处理)。排序10条记录通常不是什么大问题。

答案 2 :(得分:1)

以下是您的WHERE子句的其他几个选项,您可能希望将其与性能进行比较:

WHERE  id1 IN (id_sender, id_dest)
AND    id2 IN (id_sender, id_dest)

id_sender = id_dest可以吗?如果没有,那么您可以从第WHERE个句子

中删除第3行
WHERE  id_sender IN (id1, id2)
AND    id_dest   IN (id1, id2)
AND    id_sender <> id_dest

答案 3 :(得分:0)

没有看到解释计划,我只能猜测这个问题。我的猜测是你的最大性能打击是OR。尝试用union替换OR:

SELECT *
FROM (SELECT *
      FROM messages 
      WHERE id_sender = id1
      AND id_dest = id2
      ORDER BY message_id DESC
      LIMIT 10

      UNION

      SELECT *
      FROM messages 
      WHERE id_dest = id1
      AND id_sender = id2
      ORDER BY message_id DESC
      LIMIT 10
     ) ttbl
ORDER BY message_id ASC
LIMIT 10;