問題の歴史:
SQLクエリは最初から宣言的に設計されており、「何を取得するか」というものであって、「どのように取得するか」ではありません。DBMSのオプティマイザは実行計画(execution plan)を構築し、結合、フィルタリング、スキャン、インデックスの使用の順序を決定します。
問題:
実行計画を理解しなければ、シンプルに見えるクエリがなぜ遅く実行されるのか、逆に複雑なクエリが早く実行されるのかを説明することはできません。誤った計画は、不必要な操作やインデックスの不適切な使用によりサーバーを何時間もブロックさせることがあります。
解決策:
分析ツールには、EXPLAIN、EXPLAIN ANALYZE(PostgreSQL)、SHOW EXPLAIN(MySQL)、Management Studio Execution Plan(SQL Server)などのコマンドが含まれます。これらを使用することで、クエリがどのように実行されたか、どのくらいのデータが読み取られたか、どのインデックスが使用されたか、テーブル全体のスキャンがどこで発生したか、遅延がどこで発生したかを見ることができます。
コード例:
EXPLAIN ANALYZE SELECT * FROM orders o JOIN customers c ON o.customer_id = c.id WHERE o.status = 'shipped';
主な特徴:
インデックスを追加すれば、クエリは常に速くなるか?
いいえ!インデックスは、そのフィールドでのフィルタリングが返される行数を大幅に制限する場合にのみ効果があります。条件に合致するレコードが大半の場合、オプティマイザはインデックスを無視することがあります。
例:
-- 'gender'フィールドは2つの値しか取らないため、インデックスは役に立たない CREATE INDEX idx_gender ON people(gender); SELECT * FROM people WHERE gender = 'M';
JOIN内のテーブルの順序は、実行結果に影響を与えるか?
いいえ、最終的なデータは同じですが、オプティマイザはパフォーマンス向上のために結合の実行順序を変更することがあります。ただし、特定のJOINが記述されていたり、「JOIN HINT」などのヒントを使用した場合、順序が実行の効率に影響を与えることがあります。
実行計画の「推定行数」と「実際の行数」を分析する理由は何か?
これらの間の差は、テーブルの統計が古いか現実に合っていないことを示す可能性があり、選択された計画が最適でないことを示しています—統計を更新するか、クエリの構造を再検討する必要があります。
-- PostgreSQL ANALYZE table_name; -- 統計を更新する
プロジェクトのアナリストは、レポートの「フリーズ」に長い間不満を持っていました。5つのJOINを持つクエリは25分もかかりました。結果として、巨大なテーブルの完全スキャンが選択されており、インデックススキャンではなく、インデックスは適切なフィールドに対して設定されておらず、統計は1年間更新されていませんでした。
利点:
欠点:
実行計画を分析し、実際にフィルタリングするフィールドに対してインデックスを追加し、統計を更新しました。クエリの実行時間は20秒に短縮され、サーバーの負荷は大幅に軽減されました。
利点:
欠点: