我有一个包含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
的索引更新
答案 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
个句子
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;