Оптимизация 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;

Запрос:

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

Вопрос:

Как я могу оптимизировать его, чтобы временная таблица не использовалась?

Ответ 1

Как вы, вероятно, понимаете, проблема в том, что 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

Ответ 2

MySQL документация говорит:

Временные таблицы могут создаваться в таких условиях, как:

Если существует предложение ORDER BY и другое предложение GROUP BYили если ORDER BY или GROUP BY содержит столбцы из таблиц, отличных от первая таблица в очереди присоединения, создается временная таблица.

Таким образом, вы можете избежать использования временной таблицы только путем удаления order by Created