EXPLAIN
がGROUP BY
句を使用してクエリを実行すると、追加の条件としてfilesort
が返されることに繰り返し気付きました。ずっと前に、私はこれらのケースでGROUP BY NULL
を使用してfilesortを回避するという提案を読みましたが、実際に不快に見えるfilesort
状態を排除しています。
ORDER BY
句が存在しない場合、dbmsは、ファイルソートを必要とする不思議な列による順序付けではなく、任意の順序または最も効率的なものを提示するだけだと思います。基本的に"愚かなことは何もしない"と言ってくれる追加の指示を含める必要があるのは不思議に思えます。
私の質問は、なぜこれが必要なのか、そしてORDER BY NULL
を追加することが実際にパフォーマンスに役立つのかということです。
MySQL 5.7リファレンスマニュアル/ .../SELECT構文
GROUP BYを使用する場合、出力列は、同じ列にORDER BYがある場合と同様に、GROUP BY列に従ってソートされます。 GROUP BYが生成するソートのオーバーヘッドを回避するには、ORDER BY NULLを追加します
Using filesort
は、グループ化に使用される列に適切なインデックスがない場合に表示されます。上記のように、GROUP BY
によって返される結果は同じ列で並べ替えられます。並べ替え用にfilesort
を取得した場合、グループ化用のfilesortもあります。それは同じようにパフォーマンスを侮辱します。したがって、ソートを抑制するためではなく、インデックスを作成する必要があります。
EXPLAIN
SELECT w.t_id
, count(1) AS counter
FROM points AS w
GROUP BY w.t_id
;
+----+-------------+-------+-------+---------------+-------+---------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+-------+---------+------+----------+-------------+
| 1 | SIMPLE | w | index | t_id | t_id | 2 | NULL | 27228500 | Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+----------+-------------+
ORDER BY NULL
がなければfilesort
はありません。
SELECT w.t_id, count(1) AS counter FROM points AS w GROUP BY w.t_id;
/* Affected rows: 0 Found rows: 606 Warnings: 0 Duration for 1 query: 6,922 sec. */
SELECT w.t_id, count(1) AS counter FROM points AS w GROUP BY w.t_id ORDER BY NULL;
/* Affected rows: 0 Found rows: 606 Warnings: 0 Duration for 1 query: 6,781 sec. */
追伸.
Fidlleが失敗する限り、ここにmysql
出力があります。
複数列のインデックスなし:
+----+-------------+---------------+------+-----------------+------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+------+-----------------+------+---------+------+------+----------------------------------------------------+
| 1 | SIMPLE | animals | ALL | PRIMARY | NULL | NULL | NULL | 3 | Using temporary; Using filesort |
| 1 | SIMPLE | animal_colors | ALL | animal_id,color | NULL | NULL | NULL | 6 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+---------------+------+-----------------+------+---------+------+------+----------------------------------------------------+
2 rows in set (0.00 sec)
追加された複数列インデックス:
+----+-------------+---------------+-------+---------------------------------+-----------+---------+------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+-------+---------------------------------+-----------+---------+------------------------+------+-------------+
| 1 | SIMPLE | animals | index | PRIMARY | PRIMARY | 4 | NULL | 3 | NULL |
| 1 | SIMPLE | animal_colors | ref | animal_id,color,animal_id_color | animal_id | 4 | test.animals.animal_id | 1 | Using where |
+----+-------------+---------------+-------+---------------------------------+-----------+---------+------------------------+------+-------------+
2 rows in set (0.00 sec)