MySQLで複数の行を効率的に選択する方法:インデックスとIN句の活用
インデックスを活用して複数の行を効率的に取得する
MySQLで複数の行を効率的に選択するには、インデックスの作成とIN句の組み合わせが非常に有効です。インデックスがない状態でWHERE句による検索を行うと、フルテーブルスキャンが発生し、データ量が増えるほどパフォーマンスが低下します。ここでは、実際の手順を順番に解説していきます。
1. サンプルテーブルの作成
まず、以下のようにテーブルを作成します。
mysql> create table DemoTable1501
-> (
-> Id int NOT NULL PRIMARY KEY,
-> URL text
-> );
Query OK, 0 rows affected (0.62 sec)
2. インデックスの作成
次に、Idカラムに対してインデックスを作成します。主キーには自動的にインデックスが付与されますが、明示的に作成することも可能です。
mysql> create index id_index on DemoTable1501(Id);
Query OK, 0 rows affected (0.23 sec)
Records: 0 Duplicates: 0 Warnings: 0
3. レコードの挿入
INSERTコマンドを使用して、テーブルにサンプルデータを登録します。
mysql> insert into DemoTable1501 values(101,'www.facebook.com');
Query OK, 1 row affected (0.10 sec)
mysql> insert into DemoTable1501 values(110,'www.google.com');
Query OK, 1 row affected (0.08 sec)
mysql> insert into DemoTable1501 values(220,'www.gmail.com');
Query OK, 1 row affected (0.06 sec)
mysql> insert into DemoTable1501 values(350,'www.youtube.com');
Query OK, 1 row affected (0.08 sec)
4. 全レコードの確認
SELECT文でテーブル内のすべてのレコードを表示してみましょう。
mysql> select * from DemoTable1501;
実行結果は以下の通りです。
+-----+------------------+
| Id | URL |
+-----+------------------+
| 101 | www.facebook.com |
| 110 | www.google.com |
| 220 | www.gmail.com |
| 350 | www.youtube.com |
+-----+------------------+
4 rows in set (0.00 sec)
5. IN句で複数の行を効率的に選択する
特定の複数のIdを持つ行を一度に取得するには、IN句を使用します。OR条件を並べるよりも簡潔に書け、インデックスも適切に利用されます。
mysql> select * from DemoTable1501
-> where Id in(101,220,350);
実行結果:
+-----+------------------+
| Id | URL |
+-----+------------------+
| 101 | www.facebook.com |
| 220 | www.gmail.com |
| 350 | www.youtube.com |
+-----+------------------+
3 rows in set (0.00 sec)
6. インデックスが使われていることを確認する
本当にインデックスが利用されているのかを検証するには、SHOW STATUSコマンドでハンドラのステータスを確認します。注目すべきはHandler_read_keyの値です。これは「インデックスを使ったキー読み取りの回数」を示しており、今回の例では4つのIdのうち3つ(101・220・350)がインデックス経由で読み取られているため「3」となっています。
mysql> SHOW STATUS LIKE 'Handler_%';
実行結果:
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Handler_commit | 1 |
| Handler_delete | 0 |
| Handler_discover | 0 |
| Handler_external_lock | 2 |
| Handler_mrr_init | 0 |
| Handler_prepare | 0 |
| Handler_read_first | 0 |
| Handler_read_key | 3 |
| Handler_read_last | 0 |
| Handler_read_next | 0 |
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 0 |
| Handler_rollback | 0 |
| Handler_savepoint | 0 |
| Handler_savepoint_rollback | 0 |
| Handler_update | 0 |
| Handler_write | 0 |
+----------------------------+-------+
18 rows in set (0.00 sec)
まとめ
複数の行を効率的に選択したい場合は、対象カラムにインデックスを作成した上で、IN句を使って条件を指定するのがベストプラクティスです。さらに、Handler_read_keyなどのステータス変数を確認することで、クエリが実際にインデックスを利用しているかどうかを客観的に検証できます。大規模なデータセットを扱う際には、ぜひこの手法を活用してください。
-
MySQLでLIMITとOFFSETを使って1バッチずつ行を取得する方法
LIMITとOFFSETによるバッチ取得の基本MySQLで大量のデータを少しずつ処理したい場合、LIMIT句とOFFSET句を組み合わせるのが定番の手法です。LIMITは取得する行数を指定し、OFFSETは先頭から読み飛ばす行数を指定します。この2つを活用することで、テーブルの行を1バッチずつ順番に取り出せます。まずは、動作確認用のサンプルテーブルを作成しましょう。mysql> create table DemoTable1514 -> ( -> Id int NOT NULL AUTO_INCREMENT PRIMARY
-
MySQLで複数のテーブルの行数(COUNT(*))を1つのクエリで取得する方法
MySQLでは、サブクエリを組み合わせることで、複数のテーブルの行数を1つのクエリで同時に取得できます。基本となる構文は以下の通りです。SELECT (SELECT COUNT(*) FROM テーブル名1) AS エイリアス名1, (SELECT COUNT(*) FROM テーブル名2) AS エイリアス名2 FROM dual;構文のポイント各テーブルに対して COUNT(*) を含むスカラーサブクエリを作成し、それらを SELECT 句の中に並べます。MySQLでは FROM dual を指定することで、実際のテーブルを参照しないままサブクエリを評価できます(なお、My