SQLが遅い――その原因は複雑なロジックではなく、適切なインデックスや実行計画の理解不足にあることがほとんどです。本章では、現場で即使えるSQLパフォーマンス改善の実践テクニックを、インデックス最適化からクエリの書き換えまで、体系的に解説します。
インデックス戦略の最適化
1. カバリングインデックス(Covering Index)
カバリングインデックスとは、SELECT対象のすべての列がインデックス内に含まれている状態を指します。これにより、テーブルアクセスなしでインデックスだけでクエリを完結できます。
-- カバリングインデックス例(MySQL) CREATE INDEX idx_orders_covering ON orders (user_id, status, created_at);
以下のクエリはテーブルアクセス不要:
SELECT status, created_at FROM orders WHERE user_id = 100;
2. 結合キー最適化
JOINのパフォーマンスは、結合キーにインデックスがあるかどうかで大きく変わります。
-- NG例:JOINキーにインデックスなし SELECT * FROM orders o JOIN users u ON o.user_id = u.id;
改善策:
CREATE INDEX idx_orders_user_id ON orders(user_id); CREATE INDEX idx_users_id ON users(id);
特に片側が大テーブルの場合は、インデックスがなければネステッドループで全件走査になり、著しく遅くなります。
EXPLAIN, ANALYZE による実行計画の読み方
PostgreSQLでの分析例
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 100;
ポイントとなる出力項目:
Seq Scan:全件スキャン → インデックス未使用Index Scan:インデックスを利用した高速アクセスBitmap Index Scan:複数条件でのインデックス活用Actual Time / Rows:実際の処理時間と件数
JSON形式で構造化分析(PostgreSQL)
EXPLAIN (FORMAT JSON) SELECT * FROM orders WHERE user_id = 100;
活用例: JSON形式で保存 → 可視化ツール(pgAdmin, PEV2など)で読みやすく分析可能。
MySQLでのEXPLAIN分析
EXPLAIN SELECT * FROM orders WHERE user_id = 100;
見ておくべき項目:
type:結合タイプ(ALL, index, range, ref, eq_ref)key:使用されたインデックス名rows:スキャン対象の行数(少ないほど高速)
インデックスヒントとクエリリライト
インデックスヒントの活用
MySQLでは、オプティマイザの選択を強制するインデックスヒントが利用できます。
-- FORCE INDEXで指定インデックスを利用 SELECT * FROM orders FORCE INDEX (idx_orders_user_id) WHERE user_id = 100;
ただし、インデックスヒントは一時的な処置とし、根本的なクエリ設計の見直しが優先されるべきです。
クエリリライト(書き換え)の例
-- 非効率なパターン SELECT * FROM orders WHERE YEAR(order_date) = 2023; -- 最適化後(インデックス活用可能) SELECT * FROM orders WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31';
関数適用されたカラムはインデックスが効かないため、WHERE句の設計が重要です。
統計情報とオプティマイザの活用
統計情報とは?
統計情報とは、RDBMSが持つテーブルサイズ・カーディナリティ・値の分布などの情報で、オプティマイザ(クエリ実行プラン決定エンジン)が最適なプランを選ぶ際に使用されます。
PostgreSQLでの統計更新
ANALYZE sales;
自動更新設定の確認:
SHOW autovacuum; SHOW track_counts;
これらがOFFの場合、統計情報が古くなり、オプティマイザが誤った実行計画を選ぶリスクがあります。
MySQLでの統計確認
SHOW TABLE STATUS LIKE 'orders'; SHOW INDEX FROM orders;
MySQL 8.0以降では、より詳細な統計情報の分析も可能になっています。
まとめ
SQLパフォーマンスチューニングの本質は、インデックスとクエリ構造、統計情報のバランスを取ることにあります。
- カバリングインデックスでテーブルアクセスを回避
- EXPLAINで実行計画を可視化し、ボトルネックを発見
- クエリリライトやヒントで最適なルートを誘導
- 統計情報を定期更新して、正しい最適化判断を促す
これらを習慣化することで、SQLは「書ける」から「設計できる」スキルへと進化します。

