我有一个消息表
CREATE TABLE `messages` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`author` int(11) DEFAULT NULL,
`time` int(10) unsigned DEFAULT NULL,
`text` text CHARACTER SET latin1,
`dest` int(11) unsigned DEFAULT NULL,
`type` tinyint(4) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `author` (`author`),
KEY `dest` (`dest`)
) ENGINE=InnoDB AUTO_INCREMENT=2758 DEFAULT CHARSET=utf8;
我需要在两个用户之间收到消息
SELECT
...
FROM
`messages` m
LEFT JOIN `people` p ON m.author = p.id
WHERE
(author = 1 AND dest = 2)
OR (author = 2 AND dest = 1)
ORDER BY
m.id DESC
LIMIT 0, 25
当我解释此查询时,我得到了
请原谅任何无知,但有没有办法我可以优化这个表,以避免为此查询使用临时表和filesort,现在它不会导致问题,但我很确定将来它会麻烦吗?
答案 0 :(得分:3)
首先,我猜测left join
没有必要。其次,请考虑使用union all
。然后一种方法是:
(SELECT ...
FROM messages m JOIN
people p
ON m.author = p.id
WHERE author = 1 AND dest = 2
ORDER BY id DESC
LIMIT 25
)
UNION ALL
(SELECT ...
FROM messages m JOIN
people p
ON m.author = p.id
WHERE author = 2 AND dest = 1
ORDER BY id DESC
LIMIT 25
)
ORDER BY m.id DESC
LIMIT 0, 25
使用此查询,messages(author, dest, id)
上的索引应该使其快速。 (注意:您可能需要在m.id
列表中添加SELECT
。)
答案 1 :(得分:0)
以戈登的答案为基础:
SELECT m2..., p...
FROM
(
( SELECT id
FROM messages
WHERE author = 1
AND dest = 2
ORDER BY id DESC
LIMIT 75
)
UNION ALL
(
SELECT id
FROM messages
WHERE author = 2
AND dest = 1
ORDER BY id DESC
LIMIT 75
)
) ORDER BY id DESC
LIMIT 50, 25 ) AS m1
JOIN messages AS m2 ON m2.id = m1.id
JOIN people p ON p.id = m2.author
ORDER BY m1.id DESC
注意:
people
开始。LIMIT 75
与LIMIT 50,25
。OFFSET
"分页;有几个问题。见my blog。TEXT
列,则排序将在RAM中完成。)INDEX(author, dest, id)
时,INDEX(author)
变得多余;放下它。ALL
之后的UNION
不是UNION
的默认值,但它避免了额外的传递(和临时表)来重复数据。EXPLAIN FORMAT=JSON SELECT ...
。