私はMySQLの経験があまりなく、GROUP BY
およびCASE
ステートメントを使用して遅いクエリを高速化する方法を理解しようとしています。
ケース1-GROUP BY
およびCASE
SELECT SQL_NO_CACHE m.id, m.sku, m.movie_url
FROM movie.movies m
WHERE m.s_id = 1
GROUP BY m.mg_id, CASE WHEN m.mg_id IS NULL THEN m.id ELSE 0 END
LIMIT 100
実行時間:1.025秒、1.042秒、0.946秒
出力の説明:
+----+-------------+-------+------+--------------------+----------+---------+-------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+--------------------+----------+---------+-------+-------+----------------------------------------------+
| 1 | SIMPLE | m | ref | ind_mg_id,ind_s_id | ind_s_id | 4 | const | 39941 | Using where; Using temporary; Using filesort |
+----+-------------+-------+------+--------------------+----------+---------+-------+-------+----------------------------------------------+
ケース2-GROUP BY
なしCASE
GROUP BY
のCASE
ステートメントが遅くなる可能性があることに気付いたので、テスト目的で削除しようとしました(ただし、本番環境で使用する必要があります)。
SELECT SQL_NO_CACHE m.id, m.sku, m.movie_url
FROM movie.movies m
WHERE m.s_id = 1
GROUP BY m.mg_id#, CASE WHEN m.mg_id IS NULL THEN m.id ELSE 0 END
LIMIT 100
実行時間:0.258秒、0.149秒、0.193秒
出力の説明:
+----+-------------+-------+-------+--------------------+-----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+--------------------+-----------+---------+------+------+-------------+
| 1 | SIMPLE | m | index | ind_mg_id,ind_s_id | ind_mg_id | 9 | NULL | 2200 | Using where |
+----+-------------+-------+-------+--------------------+-----------+---------+------+------+-------------+
はるかに良いですが、それでもかなり遅いクエリです。
ケース3-GROUP BY
なし、CASE
なし
GROUP BY
ステートメントがないと、上記の時間はさらに短くなります。
SELECT SQL_NO_CACHE m.id, m.sku, m.movie_url
FROM movie.movies m
WHERE m.s_id = 1
#GROUP BY m.mg_id, CASE WHEN m.mg_id IS NULL THEN m.id ELSE 0 END
LIMIT 100
実行時間:0.053秒、0.050秒、0.052秒
出力の説明:
+----+-------------+-------+------+---------------+----------+---------+-------+-------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-------+-------+-------+
| 1 | SIMPLE | m | ref | ind_s_id | ind_s_id | 4 | const | 39941 | NULL |
+----+-------------+-------+------+---------------+----------+---------+-------+-------+-------+
詳細情報
movies
テーブルには95,600行があります。テーブルはさらに大きなサイズ(最終的には数千万)まで成長し続けます。
関連するインデックス:
+----------+------------+-------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+-------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| movies | 0 | PRIMARY | 1 | id | A | 79882 | NULL | NULL | | BTREE | | |
| movies | 1 | ind_mg_id | 1 | pg_id | A | 7262 | NULL | NULL | YES | BTREE | | |
| movies | 1 | ind_s_id | 1 | s_id | A | 10 | NULL | NULL | | BTREE | | |
+----------+------------+-------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
クエリのパフォーマンスを向上させるにはどうすればよいですか?
次のインデックスを作成してください
ALTER TABLE movie.movies ADD INDEX sid_mgid_ndx (s_id,mg_id);
このインデックスは、WHERE
およびGROUP BY
おそらく別のインデックスが役立つでしょう
ALTER TABLE movie.movies
DROP INDEX sid_mgid_ndx,
ADD INDEX sid_mgid_id_ndx (s_id,mg_id,id)
;
クエリを調整します
SELECT SQL_NO_CACHE m.id, m.sku, m.movie_url
FROM movie.movies m
WHERE m.s_id = 1
ORDER BY m.mg_id, m.id;
LIMIT 100;
GROUP BY
からORDER BY
実際の集計を行っていないため(つまり、SUM()、COUNT()、AVG()、またはその他の合計を行っていないため)