LASSIC Media らしくメディア

2026.08.10 らしくコラム

スロークエリの直し方|EXPLAINで原因を切り分け

「画面の表示が急に遅くなった」「バッチ処理が終わらない」——原因を追っていくと、その多くはデータベースへの1本のクエリが想定以上に時間をかけていることに行き着きます。いわゆるスロークエリです。厄介なのは、開発時は問題なく動いていたクエリが、データ量が増えた後になって初めて遅さが表面化する点です。

スロークエリ自体は珍しい現象ではありませんが、見つけ方と直し方の手順を知っているかどうかで対応の速さが大きく変わります。本記事では、発注担当者やプロジェクトマネージャーに向けて、スロークエリの検知方法・原因の切り分け方・EXPLAINを使った実行計画の読み方・対策の進め方を整理します。

データベースサーバーのイメージ

スロークエリとは——まず何を見て気づくか

スロークエリとは、実行に想定より長い時間がかかっているデータベースへの問い合わせのことです。定義自体に厳密な秒数のしきい値はなく、業務要件に対して遅いかどうかで判断します。決済処理で1秒かかるクエリは遅いとみなされる一方、夜間バッチの集計処理で数秒かかること自体は問題にならない、といった具合です。

気づく手段として代表的なのが、データベースが標準で備えているスロークエリログです。しきい値を超えた実行時間のクエリを自動的に記録する機能で、MySQLではslow_query_logを有効にすることで利用できます*1。PostgreSQLであればlog_min_duration_statementで同様のログを取得できます。加えて、実行中のクエリをリアルタイムに確認できるperformance_schemaのようなビューや、APM(アプリケーション監視)ツールのクエリ単位のトレースも、遅いクエリを特定する手がかりになります。

厄介なのは、開発環境で動作確認をしたときは問題なく動いていたクエリが、本番運用に入ってから遅くなるケースが少なくない点です。よくある背景として、データ量が開発時の想定より増え、テーブルの規模がスキャンにかかる時間に直結するようになった、同時にアクセスするユーザー数が増えてロック待ちや競合が発生しやすくなった、キャッシュが効きにくいアクセスパターンに変わった、といった事情が挙げられます。開発時のテストだけで「問題なし」と判断せず、本番相当のデータ量や負荷を想定した確認を組み込んでおくと、後になって気づくケースを減らしやすくなります。

この記事のポイント

  • スロークエリの発見には、データベース標準のスロークエリログやperformance_schemaが役立ちます。
  • 原因の多くは、インデックス未使用・N+1・非効率なJOINの3系統に集約されます。
  • EXPLAINで実行計画を確認し、対策後は再度EXPLAINで効果を検証する流れが基本です*2

原因の切り分け——よくある3パターン

スロークエリの原因は多岐にわたりますが、実務でよく遭遇するのは次の3パターンです。

パターン 特徴 見分け方の目安
インデックス未使用 検索条件に使う列にインデックスがなく、テーブル全体を読みに行っている。 実行計画にフルテーブルスキャンやシーケンシャルスキャンが現れる。
N+1問題 1件ずつ関連データを取りに行い、同じ形のクエリが繰り返し発行される。 ログ上で同一パターンのクエリが件数分だけ連続して並ぶ。
非効率なJOIN・集計 結合対象のテーブルが大きい、または結合条件が適切でない。 実行計画で想定より多い行数が結合・並び替えの対象になっている。

N+1問題については、それ自体の仕組みと対策を別記事で詳しく解説しています。インデックスの設計判断に関わる「値の種類の多さ」についてはカーディナリティの考え方、インデックスの内部構造についてはB-treeインデックスの解説もあわせて参考にしてください。本記事では、これらの原因をどう見つけ、どう対策するかという実務の進め方に絞って整理します。

EXPLAINで実行計画を読む

遅いクエリを見つけた後は、そのクエリの前にEXPLAINを付けて実行することで、データベースがどういう手順で処理を進めているかという実行計画を確認できます*1*2。MySQLのEXPLAINであれば、テーブルへのアクセス方法を示すtype列や、走査する行数の見積もりを示すrows列、使用中のインデックスを示すkey列が確認の起点になります*2typeALL(フルテーブルスキャン)になっている、あるいはrowsの見積もりが実際のデータ量に対して大きすぎる場合は、インデックスが使われていない可能性を疑います。

全体の対応フローを図にすると、次のようになります。検知→実行計画の確認→原因特定→対策実施→効果検証というサイクルを、改善が不十分であれば繰り返す流れです。

スロークエリ対応の基本フローの図

PostgreSQLではEXPLAIN ANALYZEを使うと、見積もりだけでなく実際の実行時間や行数も確認できます*1。見積もり(推定行数)と実測(実際の行数)が大きくずれている場合は、テーブルの統計情報が古くなっている可能性があるため、統計情報の更新(ANALYZEコマンドなど)も対策の選択肢に入ります。

MySQLのEXPLAINにはほかにも、テーブルの読み取り順序を示すid列、使用可能なインデックスの一覧を示すpossible_keys列、絞り込みの効率を示すfiltered列(見積もり行数のうちどの割合が条件に合致するかの推定)などがあります*2。読み慣れないうちはtyperowsだけでもよいので、まずは「フルスキャンになっていないか」「見積もり行数が実データに対して大きすぎないか」の2点を確認する習慣をつけると、原因の切り分けが早くなります。複数テーブルを結合するクエリでは、結合される側のテーブルにもインデックスが効いているかを、テーブルごとに1行ずつ確認していく進め方だと見落としを減らせます。

原因別の対策

原因が絞り込めたら、それぞれに応じた対策を検討します。

原因 対策の方向性
インデックス未使用 検索・絞り込みに使う列へインデックスを追加する。複数列を組み合わせて検索する場合は複合インデックスも検討する。
N+1問題 関連データをまとめて1回のクエリで取得するよう、アプリケーション側のデータ取得方法を見直す。
非効率なJOIN・集計 結合順序や結合条件を見直す、あるいは集計処理を事前に別テーブルへ持たせる設計に変更する。
統計情報の陳腐化 テーブルの統計情報を更新し、実行計画の見積もりを実データに近づける。

対策を適用した後は、もう一度EXPLAINを実行し、フルテーブルスキャンが解消したか、走査する行数が減ったかを確認します。実行時間だけを見て終わらせず、実行計画の変化まで確認しておくと、たまたま速く見えただけという見落としを防ぎやすくなります。

見落としがちな落とし穴

スロークエリ対策は、やればやるほど良いというものではありません。運用段階で見落としがちな点を挙げます。

落とし穴 内容
インデックスの過剰追加 インデックスを増やすほど検索は速くなりやすい一方、書き込み時の更新コストが増え、テーブルの容量も膨らむ。
本番データでの検証不足 開発環境のデータ量が本番より少ないと、実行計画の傾向が本番と食い違うことがある。
1回の計測で判断する キャッシュの状態やその時点の負荷で実行時間はばらつくため、複数回の計測で傾向を見る方が判断がぶれにくい。
アプリケーション側の見落とし クエリ自体は妥当でも、呼び出し回数や呼び出し頻度そのものが多すぎるケースは、データベース側の対策だけでは解決しない。

外注時に確認しておきたい点

スロークエリ対応を外部に依頼する場合は、事前に次の点をすり合わせておくと、対応の範囲や進め方の認識ずれを防ぎやすくなります。まず、対象となるクエリやログをどの環境(開発・検証・本番)から取得するか。次に、EXPLAINなどの調査結果をどの粒度で報告してもらうか。そして、インデックス追加のようにデータベースの構造を変える対策を行う場合、本番環境への適用タイミングと切り戻し方針をどう決めるか——この3点です。

また、単発の調査で終わらせるか、継続的な監視の仕組み(スロークエリログの定期確認やアラート設定)まで含めて依頼するかによって、対応の範囲は大きく変わります。データ量が増え続けるシステムでは、一度きりの対策よりも、遅いクエリを早期に検知できる仕組みを併せて整えておく方が、後々の負担を抑えやすくなります。

まとめ:スロークエリ対応で押さえる3つの視点

スロークエリへの対応は、闇雲にインデックスを追加するのではなく、順序立てて進めることで効率が上がります。第一に、スロークエリログなどで遅いクエリを正しく検知すること。第二に、EXPLAINで実行計画を確認し、フルテーブルスキャン・N+1・非効率なJOINのどれに当たるかを切り分けること。第三に、対策の適用後も再度実行計画を確認し、効果を数字で検証すること。この3つの視点を押さえておけば、場当たり的な対応から抜け出しやすくなります。データベースの性能に不安があれば、調査の段階から外部の知見を借りるのも一つの選択肢です。

LASSICに相談するメリット

LASSIC IT事業部は、元請(プライムベンダー)としてシステム開発とデータベース運用の改善を一貫して受託しています。スロークエリの調査からインデックス設計、アプリケーション側のデータ取得方法の見直しまで、工程を分断せずに対応できるのが強みです。現在のデータベースのパフォーマンスについて、調査の段階からご相談いただけます。

よくある質問

スロークエリかどうかは、何秒を基準に判断すればよいですか。

明確な秒数の基準はなく、業務要件に対して遅いかどうかで判断します。決済処理のように即時性が求められる処理では1秒未満でも遅いとみなされることがあり、夜間バッチのように即時性を求めない処理では数秒かかっても問題にならないことがあります。まずは自社の処理ごとに許容できる時間を決めるところから始めるとよいでしょう。

インデックスを追加すれば、スロークエリは解消しますか。

原因がインデックス未使用によるものであれば効果が見込めますが、N+1問題や非効率なJOINが原因の場合はインデックスだけでは解消しません。EXPLAINで実行計画を確認し、原因を切り分けたうえで対策を選ぶことが重要です。

EXPLAINとEXPLAIN ANALYZEの違いは何ですか。

EXPLAINは実行計画の見積もりを表示するのに対し、EXPLAIN ANALYZE(PostgreSQLなど)は実際にクエリを実行し、実測の行数や時間も併せて確認できます。見積もりと実測が大きくずれている場合は、統計情報の更新も対策の候補になります。

本番環境でEXPLAINを実行しても問題ありませんか。

EXPLAIN自体はクエリの実行計画を確認するだけで、通常はデータを変更しないため実行しても差し支えないケースが多いです。ただしEXPLAIN ANALYZEは実際にクエリを実行するため、更新系のクエリや負荷の高いクエリに対しては、実行タイミングや対象環境に配慮した方がよいでしょう。

外注する場合、どこまで依頼できますか。

スロークエリの調査・原因の切り分けといった単発の対応から、インデックス設計、アプリケーション側のデータ取得方法の見直し、継続的な監視の仕組みづくりまで、範囲を分けて依頼できます。対象環境と報告の粒度、本番適用の方針をあらかじめすり合わせておくと進めやすくなります。

著者:テレリモ総研編集部 鈴木 亮佑

データベースの性能改善のご相談はLASSICへ

元請(プライムベンダー)として、スロークエリの調査からインデックス設計・実装・運用まで、貴社の課題に合わせてご提案します。まずはお気軽にご相談ください。

無料相談はこちら

ご不明な点はお問い合わせフォームからもご連絡いただけます。

  1. *1 出典:PostgreSQL Documentation「EXPLAIN」(https://www.postgresql.org/docs/current/sql-explain.html
  2. *2 出典:MySQL 8.0 Reference Manual「The Slow Query Log」「EXPLAIN Output Format」(https://dev.mysql.com/doc/refman/8.0/en/slow-query-log.htmlhttps://dev.mysql.com/doc/refman/8.0/en/explain.html


View