MySQLのインデックスについて、初心者向けにわかりやすく解説します。
インデックスとは?
インデックスとは、データベースの特定のカラム(または複数のカラム)に対して作成されるデータ構造です。
このデータ構造は、書籍の索引のような役割を果たし、検索やソート、ジョインのパフォーマンスを向上させます。
インデックスが存在することで、データベースはテーブル内の多くの行をスキャンすることなく、迅速にデータにアクセスできるようになります。
しかし、正しくインデックスを作成しないと、かえってパフォーマンスを低下させてしまう要因にもなります。
この記事では、初学者向けにインデックスについて解説します。
インデックスの作成
早速ですが、インデックスがどのようにパフォーマンスを向上させるのか、具体的な例を用いて解説したいと思います。
まず例として、従業員情報を管理するテーブルを作成します。
CREATE TABLE employees (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100),
department VARCHAR(50),
age INT,
hire_date DATE
);
次にテストデータをINSERTします。
INSERT INTO employees (name, email, department, age, hire_date) VALUES
('田中', 'a@example.com', 'HR', 30, '2021-01-15'),
('佐藤', 'b@example.com', 'Engineering', 25, '2019-07-07'),
('栗原', 'c@example.com', 'Sales', 35, '2018-09-22'),
('石井', 'd@example.com', 'Engineering', 45, '2015-03-16'),
('森', 'e@example.com', 'Finance', 29, '2020-11-11');
まずはこのデータに対して、インデックスを使用せずに検索してみます。
例えば、Engineering部署の全ての従業員を検索するSELECT文の実行計画を見てみます。
実行計画は、SELECTの前にEXPLAINをつけると確認することができます。
EXPLAIN SELECT * FROM employees WHERE department = 'Engineering';
色々出てきますが、最初に着目頂きたいのはtypeの列です。
「ALL」と書かれていて、全ての行をスキャンする「全表スキャン(Full Table Scan)」が行われていることがわかります。
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | employees | NULL | ALL | NULL | NULL | NULL | NULL | 5 | 20.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
今回の例のように、テーブルが小さい場合はそれほど問題にはなりませんが、大規模なデータベースでは検索時間が長くなります。
では、次にインデックスを追加してみましょう。
今回はシンプルに、「department」カラムにインデックスを追加します。
CREATE INDEX idx_department ON employees (department);
再度先ほどのSELECT文の実行計画を確認してみます。
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | employees | NULL | ref | idx_department | idx_department | 203 | const | 2 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
type列が「ref」に変わっていること、またrows(検索に読み取る必要がある推定レコード数)列が、5→2に変わっていることからも、フルスキャンが回避できたことを確認できます。
注意点
インデックスの作成は、MySQLのパフォーマンスを上げるのに重要な作業です。
その一方で、実行計画をちゃんと確認せずに、インデックスをただ作成してしまうと、せっかく使ったインデックスが使われていなかったり、逆にパフォーマンスを下げてしまう場合もあります。
またありがちなミスとして、テスト環境でうまく使われていたインデックスでも、本番環境で実行した場合に、データ量の差がありすぎて、うまくインデックスが効かないといったケースがあります。
そのため、インデックスを作成する場合は、できる限り本番環境に近いデータを用意した上で、実行計画を細かく確認しながら、チューニングしていくことを心がけてください。
最後に・・
いかがでしたでしょうか?
今回はインデックスを貼ったことがないような初学者の方に向けて、インデックスについて解説してみました。
なかなか結果が分かりやすく見えない点から、最初は苦労するかもしれませんが、実行計画を何度も確認しながら、SQLのパフォーマンスを上げていけるようにトライしてみましょう。