表:
CREATE TABLE `T1` (
`UserId` int(10) unsigned NOT NULL,
`FriendUserId` int(10) unsigned NOT NULL,
`IsDisplayed` tinyint(1) unsigned NOT NULL,
`Created` datetime NOT NULL,
KEY `FriendUserId` (`FriendUserId`,`IsDisplayed`,`UserId`,`Created`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
查询:
SELECT `UserId`, `FriendUserId`, UNIX_TIMESTAMP(`Created`) AS `Created`
FROM `T1` WHERE `FriendUserId` = 22
AND `IsDisplayed` = 0
GROUP BY `UserId`
ORDER BY `Created`
EXPLAIN结果:
id: 1
select_type: SIMPLE
table: T1
type: ref
possible_keys: FriendUserId
key: FriendUserId
key_len: 5
ref: const,const
rows: 1
Extra: Using where; Using index; Using temporary; Using filesort
问题:
如何优化它以便不使用临时表?
答案 0 :(得分:11)
MySQL documentation说:
可以在以下条件下创建临时表:
如果有
ORDER BY
子句和不同的GROUP BY
子句, 或者如果ORDER BY
或GROUP BY
包含除了表之外的列 在连接队列中的第一个表中,创建了一个临时表。
因此,您只能通过删除order by Created
答案 1 :(得分:4)
正如您可能理解的那样,问题是GROUP BY
按UserId
订购数据,但结果集应按Created
排序;因此,MySQL将输出放在临时表中,对其进行排序和输出。
诀窍可能是强制立即以Created
顺序输出不同的行。
我想到的第一个是这样的:
SELECT DISTINCT
UserId,
FriendUserId,
UNIX_TIMESTAMP(`Created`) AS `Created`
FROM T1
WHERE FriendUserId = 22 AND IsDisplayed = 0
ORDER BY `Created`
并将索引更改为(FriendUserId, IsDisplayed, Created, UserId)
。
或具有相同索引的另一个查询:
SELECT
UserId,
FriendUserId,
UNIX_TIMESTAMP(`Created`) AS `Created`
FROM T1
WHERE FriendUserId = 22 AND IsDisplayed = 0
GROUP BY `Created`, UserId