MySQLのEXPLAINコマンドでORDER BYの実行計画を確認する方法
はじめに
MySQLではEXPLAINコマンドを使うことで、SELECT文が内部でどのように実行されるか(実行計画)を確認できます。本記事では、ORDER BY句と組み合わせた場合に、インデックスがどのように利用されるのか、Extra列に表示される「Using filesort」「Using temporary」の意味などを、実際のコード例とともに解説します。
サンプルテーブルの作成
まず、以下のクエリでテーブルを作成します。Id列にはAUTO_INCREMENT付きの主キー(PRIMARY KEY)を設定しています。
mysql> create table DemoTable606 (Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,FirstName varchar(100)); Query OK, 0 rows affected (0.56 sec)
レコードの挿入
続いて、INSERTコマンドでいくつかのレコードを登録します。
mysql> insert into DemoTable606(FirstName) values('John');
Query OK, 1 row affected (0.15 sec)
mysql> insert into DemoTable606(FirstName) values('Robert');
Query OK, 1 row affected (0.14 sec)
mysql> insert into DemoTable606(FirstName) values('Chris');
Query OK, 1 row affected (0.13 sec)
mysql> insert into DemoTable606(FirstName) values('David');
Query OK, 1 row affected (0.13 sec)
レコードの確認
SELECT文ですべてのレコードを表示してみましょう。
mysql> select *from DemoTable606;
実行結果は以下の通りです。
+----+-----------+ | Id | FirstName | +----+-----------+ | 1 | John | | 2 | Robert | | 3 | Chris | | 4 | David | +----+-----------+ 4 rows in set (0.00 sec)
EXPLAINコマンドでORDER BYの挙動を確認する
それでは、EXPLAINコマンドを使って、異なるORDER BY句が実行計画にどのような影響を与えるのかを順番に見ていきましょう。
パターン1:主キー(Id)のみで並べ替え
mysql> explain select * from DemoTable606 order by Id; +----+-------------+--------------+------------+-------+---------------+---------+---------+------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+-------+---------------+---------+---------+------+------+----------+-------+ | 1 | SIMPLE | DemoTable606 | NULL | index | NULL | PRIMARY | 4 | NULL | 4 | 100.00 | NULL | +----+-------------+--------------+------------+-------+---------------+---------+---------+------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
この結果では、key列にPRIMARYが選択され、typeはindexになっています。Idは主キーであり、データがすでにインデックス順に格納されているため、余分なソート処理は一切発生していません。これが最も効率的な形です。
パターン2:IdとFirstNameで並べ替え
mysql> explain select * from DemoTable606 order by Id,FirstName; +----+-------------+--------------+------------+------+---------------+------+---------+------+------+----------+----------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+------+------+----------+----------------+ | 1 | SIMPLE | DemoTable606 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using filesort | +----+-------------+--------------+------------+------+---------------+------+---------+------+------+----------+----------------+ 1 row in set, 1 warning (0.00 sec)
今度はExtra列にUsing filesortと表示されました。FirstName列にはインデックスが存在しないため、MySQLはインデックスだけでは並べ替えを完結できず、メモリやディスク上で追加のソート処理を行う必要があるからです。typeもALL(フルテーブルスキャン)に変わっている点に注目してください。
パターン3:RAND()を使った並べ替え
mysql> explain select * from DemoTable606 order by Id,RAND(); +----+-------------+--------------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+ | 1 | SIMPLE | DemoTable606 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using temporary; Using filesort | +----+-------------+--------------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+ 1 row in set, 1 warning (0.00 sec)
RAND()のような関数をORDER BYに使うと、Extra列にUsing temporary; Using filesortと表示されます。これは、一時テーブルの作成とその後のソート処理の両方が行われていることを意味し、3つのパターンの中で最もパフォーマンスへの負荷が大きい形になります。
まとめ
EXPLAINの実行結果から読み取るべき主なポイントは以下の通りです。
- key列:実際に使用されたインデックス。NULLの場合はインデックスが使われていません。
- type列:indexならインデックススキャン、ALLならフルテーブルスキャンを示します。
- Extra列:Using filesortやUsing temporaryが表示される場合は、追加のソート・一時テーブル処理が発生しており、大規模なデータではボトルネックになり得ます。
ORDER BYの対象列に適切なインデックスを設定することで、filesortを回避し、クエリを大幅に高速化できます。パフォーマンスチューニングの第一歩として、ぜひEXPLAINコマンドを活用してみてください。
-
MySQLのORDER BYでCASE WHENを使って独自の順序でソートする方法
MySQLのORDER BYでCASE WHENを使う MySQLでは、ORDER BY句の中でCASE WHEN(CASE式)を組み合わせることで、アルファベット順や数値順ではなく、独自に定義した任意の順序でレコードを並べ替えることができます。 「特定の値を先頭に表示したい」「カテゴリごとに優先順位をつけたい」といったケースで非常に便利なテクニックです。以下、具体例を見ていきましょう。 1. サンプルテーブルの作成 まずはテーブルを作成します。 mysql> create table DemoTable( Color varchar(100) ); Query OK, 0 ro
-
MySQLでNULLを含む列の乗算を処理する方法|COALESCE関数の使い方
MySQLでNULLを含む列の乗算を正しく計算するにはMySQLでは、数値型の列にNULLが含まれている場合、そのまま乗算すると結果もNULLになってしまいます。このような問題を回避するには、COALESCE() 関数を利用するのが効果的です。COALESCE()は、引数の中から最初に見つかった非NULLの値を返す関数で、NULLを別の値(ここでは「1」)に置き換えて計算できます。以下、実際の手順を見ていきましょう。1. サンプルテーブルを作成するまず、商品点数と金額を格納するテーブルを作成します。mysql> create table DemoTable1842 &nbs