SQL查询优化以避免使用临时表

14

这个表格:

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`

解释结果:

           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

问题:

如何进行优化,以便不使用临时表?

2个回答

12

MySQL 文档 表示:

在以下情况下可以创建临时表:

如果有 ORDER BY 子句和不同的 GROUP BY 子句,或者如果 ORDER BYGROUP BY 包含来自连接队列中第一个表以外的表的列,则会创建一个临时表。

因此,只有通过删除 order by Created 才能避免使用临时表。


4

你可能已经理解,问题在于GROUP BYUserId对数据进行排序,但结果集应该按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

我不明白...根据您所做的修改,它不再按创建时间排序了... - yeahman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接