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`

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

質問:

一時テーブルが使用されないように最適化するにはどうすればよいですか?

4

2 に答える 2

12

MySQLのドキュメントには次のように記載されています。

一時テーブルは、次のような条件下で作成できます。

ORDER BY句と別の句があるGROUP BY場合、ORDER BYまたは またはGROUP BYに結合キューの最初のテーブル以外のテーブルの列が含まれている場合、一時テーブルが作成されます。

したがって、削除することによってのみ一時テーブルの使用を回避できますorder by Created

于 2012-08-10T06:22:17.910 に答える
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
于 2012-08-10T09:12:04.073 に答える