0

我有一个包含 500 万行的消息表,我想检索两个用户对话的最后 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

4 回答 4

3

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

其次,一些想法:

  • SELECT *如果没有必要,不要使用。只需带回所需的字段。
  • 这是建立在第一个之上的。建立一个覆盖索引。这意味着如果字段在任何地方a, b, c的查询中使用,那么您可以在表上建立索引。这将允许数据库读取索引页,而不必从数据页中查找、加载和读取。a, b, c
于 2013-08-05T16:06:39.787 回答
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 条记录进行排序通常没什么大不了的。

于 2013-08-05T16:09:30.133 回答
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
于 2013-08-05T16:21:08.867 回答
0

没有看到解释计划,我只能猜测问题。我的猜测是你最大的性能打击是 OR。尝试用联合替换 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;
于 2013-08-05T20:02:47.517 回答