SQL Query优化避免临时表

Rom*_*aza 12 mysql sql

桌子:

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;
Run Code Online (Sandbox Code Playgroud)

查询:

SELECT `UserId`, `FriendUserId`, UNIX_TIMESTAMP(`Created`) AS `Created`
FROM `T1` WHERE `FriendUserId` = 22
  AND `IsDisplayed` = 0
  GROUP BY `UserId`
  ORDER BY `Created`
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

题:

如何优化它以便不使用临时表?

Cyb*_*m0n 12

MySQL 文档说:

可以在以下条件下创建临时表:

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

因此,您只能通过删除来避免使用临时表 order by Created


new*_*ver 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`
Run Code Online (Sandbox Code Playgroud)

并将索引更改为(FriendUserId, IsDisplayed, Created, UserId).

或者具有相同索引的另一个查询:

SELECT
  UserId,
  FriendUserId,
  UNIX_TIMESTAMP(`Created`) AS `Created`
FROM T1
WHERE FriendUserId = 22 AND IsDisplayed = 0
GROUP BY `Created`, UserId
Run Code Online (Sandbox Code Playgroud)