EXPLAINでインデックスの効きを確認する

入門 | 12分 で読める | 2026.06.17

公式ドキュメント

今回やること

この記事では、EXPLAIN を使って、SQLがテーブルをどう探そうとしているかを確認します。

インデックスは作るだけでなく、EXPLAINで使われているか確認することが大切です。

前提条件

  • PostgreSQLなど EXPLAIN を使える環境がある
  • SELECTWHERE の基本を知っている
  • 結果表示はデータベースやバージョンによって少し異なる

Step 1: 練習用テーブルを作る

CREATE TABLE customers (
  id INTEGER PRIMARY KEY,
  email TEXT NOT NULL,
  name TEXT NOT NULL
);

Step 2: データを入れる

少量データでは違いが見えにくいですが、手順を確認する目的で数件入れます。

INSERT INTO customers (id, email, name) VALUES
  (1, 'sato@example.com', 'Sato'),
  (2, 'suzuki@example.com', 'Suzuki'),
  (3, 'tanaka@example.com', 'Tanaka');

大量データで試す場合は、学習用DBで別途データを増やしてください。

Step 3: EXPLAINを実行する

EXPLAIN
SELECT *
FROM customers
WHERE email = 'sato@example.com';

インデックスがない状態では、Seq Scan のような表示になることがあります。これは順番にテーブルを確認する全件スキャンです。

Step 4: インデックスを作る

CREATE INDEX idx_customers_email
ON customers (email);

email を検索条件に使うため、email にインデックスを作ります。

Step 5: もう一度EXPLAINする

EXPLAIN
SELECT *
FROM customers
WHERE email = 'sato@example.com';

行数が少ないテーブルでは、インデックスを作っても Seq Scan のままになることがあります。これは異常とは限りません。データベースが「この件数なら全件見た方が早い」と判断する場合があるからです。

インデックスを作ったのに使われないことはあります。EXPLAINで実際の計画を見ます。

Step 6: EXPLAIN ANALYZEの注意

PostgreSQLでは EXPLAIN ANALYZE を使うと、実際にSQLを実行して時間も測ります。

EXPLAIN ANALYZE
SELECT *
FROM customers
WHERE email = 'sato@example.com';

SELECT なら比較的安全ですが、UPDATEDELETE に対して使うと実際に変更が走ります。変更系SQLで使う場合はトランザクションや検証環境で慎重に扱います。

Step 7: JOINで使う列を考える

注文テーブルの user_id のように、JOINでよく使う列もインデックス候補です。

CREATE INDEX idx_orders_user_id
ON orders (user_id);

JOINが遅いときは、JOIN条件に使う列がインデックス候補になることがあります。

よくあるエラー

エラーよくある原因確認すること
インデックスが使われない行数が少ない異常とは限らない
EXPLAIN ANALYZE で変更された更新系SQLに使った検証環境とトランザクションを使う
インデックス名が重複同じ名前で作成済み\di などで一覧確認
期待より速くない条件に合っていないWHERE/JOIN/ORDER BYの列を確認

まとめ

EXPLAIN は、SQLがどのように実行されそうかを見るための道具です。Seq Scan は全件スキャン、Index Scan はインデックス利用の目安になります。インデックスを作ったら、実際に使われているか EXPLAIN で確認します。

参考リソース

← 一覧に戻る
PR
PR
PR
PR