LASSIC Media らしくメディア
外部エンジニアのSQLチューニング、性能改善の目標から決める
監修・編集責任者:牛尾 昭昌(株式会社LASSIC 執行役員)
この記事の結論
- 外部エンジニアに頼む前に、機能ごとの応答時間と、その時間内に収まる割合で性能改善の目標を決めます。
- 直す候補は、SQLごとの実行時間の合計と平均を一覧にし、記録を始めた日時とあわせて外部エンジニアに渡します。
- 実行計画を取る環境、実行されたSQL文を見られる権限、変更を承認する人は、社内で決めてから伝えます。
※ 本記事は2026年9月時点の公式情報(省庁・公的機関、および製品やサービスを提供する事業者が公開している資料)に基づきます。
画面が遅いと言われて外部エンジニアに調べてもらったものの、どこまで速くなれば終わりなのかが決まっていない。検証環境では速くなったのに、本番に入れると遅いまま——。データベースの性能改善を社外の人に頼む現場では、こうした食い違いが起こりがちです。SQLチューニングとは、SQL(データベースへの命令文)の書き方や索引(検索用に別に作るデータ)などを見直し、データベースが選ぶ処理の手順を速いものに変える作業のことです。
データベースが選んだ処理の手順は実行計画と呼ばれ、これを読み慣れた外部エンジニアに加わってもらうのは、社内に経験者がいないときの現実的な方法です。ただし万能ではなく、目標の数値と調べるための材料は社内でそろえておく必要があります。本記事では、開発の現場を預かるマネージャーに向けて、SQLチューニングの中身、性能改善の目標の決め方、どのSQLから直すか、外部エンジニアに渡す権限と資料、つまずきやすい点、そして外部に委託するときに確認しておきたい点を整理します。
目次
SQLチューニングとは
ここでは、PostgreSQLの公式ドキュメント(PostgreSQL 18)を例にします。PostgreSQLは、受け取ったSQLごとに実行計画を立てます。ドキュメントは、SQLの構造とデータの性質に合った計画を選ぶことが性能にとって決定的に重要だと説明しており、計画を選ぶ仕組みはプランナーと呼ばれます。*1 どの計画が選ばれたかは、EXPLAINという命令で確かめられます。
プランナーは、条件に合う行が何行ありそうかを見積もって計画を選びます。見積もりに使うのが統計情報で、テーブルの行数やディスク上の大きさ、列の値の分布などが記録されています。列の値の分布はANALYZEやVACUUM ANALYZEという命令で更新されますが、更新した直後でも概算の値です。*2
SQLチューニングで手を入れる代表的なものは、SQLの書き方、索引の作成と見直し、統計情報の更新の3つです。どれを選ぶかは、テーブルの読み込みや結合など、手順のどの部分で時間がかかっているかを見て決めます。機能の名前や設定の方法はデータベースの製品ごとに違うため、MySQLやOracle Databaseを使っている場合は、それぞれの公式ドキュメントで対応する機能を確かめます。
性能改善の目標をどう決めるのか
「速くしてほしい」だけでは、外部エンジニアはどこで作業を終えればよいのかを判断できません。目標の立て方の手がかりになるのが、IPA(独立行政法人情報処理推進機構)の「非機能要求グレード2018」です。性能・拡張性の「性能目標値」では、オンラインの処理に求めるレスポンスについて、通常時・ピーク時・縮退運転時(一部の機器が止まり、能力を落として動く状態)ごとに順守率を決めるとしています。順守率は、決めた時間内に応答できた処理の割合です。
通常時レスポンス順守率のレベルは、「順守率を定めない」から60%、80%、90%、95%、99%以上までの6段階です。*3 ただし、このレベルは「おおまかな目安を示しており、具体的にはレスポンスと順守率について数値で合意する必要がある」とされています。*3 具体的な数値は、Webシステムの参照系・更新系・一覧系(データを見る画面、登録や変更をする画面、一覧を出す画面)のように、機能やシステムの分類ごとに決めておくことが望ましいとも書かれています。
IPAのセミナー資料には、発注処理について「通常時のオンラインレスポンスは3秒以内とし、その順守率は95%以上とする」という要求の例があります。*4 SQLチューニングを頼むときも、この形で目標を書けます。たとえば「受注一覧の検索は3秒以内を95%以上」「月次の集計処理は翌朝の始業までに終える」のように、機能ごとに時間と割合を決めておけば、作業が終わったかどうかを外部エンジニアと同じ基準で判断できます。
どのSQLから直すのか
遅いと言われた画面のSQLだけを見ていると、ほかの処理がデータベースの時間を多く使っていることに気づけない場合があります。PostgreSQLには、サーバーで実行されたすべてのSQLについて、実行回数や時間などの統計を記録するpg_stat_statementsという拡張機能があります。*5 実行回数(calls)、実行時間の合計(total_exec_time)、平均(mean_exec_time)などがSQLごとに記録され、時間の単位はミリ秒です。
顧客番号のように条件の値だけが違うSQLは、1つの行にまとめて集計されます。顧客番号だけが違う検索が1万回実行されていれば、1行に1万回分の時間が集まるということです。1回あたりは速くても回数の多いSQLは合計が大きくなるので、合計時間の上位と、平均が目標の時間を超えているSQLの両方を一覧にして渡すと、どれから直すかを外部エンジニアと相談しやすくなります。
注意したいのは、この拡張機能を使い始めるには、設定ファイル(shared_preload_libraries)を変えたうえでサーバーを再起動する必要がある点です。*5 再起動には業務との調整が要るので、外部エンジニアが加わる前に有効にして、ふだんの負荷で数日分の記録をためておくと、初日から一覧をもとに話を始められます。遅いSQLだけをログに残したいときは、log_min_duration_statementという設定で、指定した時間以上かかったSQLの実行時間を記録する方法もあります。
外部エンジニアに渡す権限と資料
pg_stat_statementsの一覧は、だれでも全部を見られるわけではありません。ほかのユーザーが実行したSQL文を見られるのは、スーパーユーザー(すべての権限を持つ管理者)と、pg_read_all_statsというロール(権限のまとまり)の権限を持つユーザーに限られます。*5 外部エンジニアにこのロールを付けるのか、社内の担当者が一覧を書き出して渡すのかを、作業を始める前に決めておきます。
実行計画の取り方にも決まりが要ります。EXPLAINにANALYZEを付けると、SQLは計画されるだけでなく実際に実行され、各段階の実際の行数と時間が表示されます。結果の行は画面に返されませんが、更新や削除のSQLならデータは実際に書き換わります。そのため、BEGINで始めてROLLBACKで元に戻す手順がドキュメントに示されています。*6 本番のデータベースでANALYZE付きのEXPLAINを流してよいのか、流すならどの時間帯かを、社内で決めて伝えます。
渡す資料は、次のようにまとめておくと作業を始めやすくなります。
| 資料 | 中身の例 |
|---|---|
| 性能の目標 | 機能ごとの応答時間と順守率(例:受注一覧の検索は3秒以内を95%以上) |
| 直す候補のSQL | pg_stat_statementsから書き出した、合計時間の上位と、平均が目標を超えるSQL。記録を始めた日時も添える |
| 実行計画 | 本番に近いデータ量の環境で取った、ANALYZE付きのEXPLAINの結果 |
| データ量 | 主なテーブルの行数と、ディスク上の大きさ |
| 作業の決まり | ANALYZE付きのEXPLAINを実行してよい環境と時間帯、索引の追加やSQLの書き換えを承認する人 |
表のうち、性能の目標と作業の決まりは、社内でしか決められない項目です。直す候補のSQLと実行計画は、権限を渡せば外部エンジニアが自分で集めることもできます。その場合も、社内と外部エンジニアで同じ期間の記録と同じデータ量の環境を使うと、変更の前後を比べやすくなります。
つまずきやすい点
一つ目は、検証環境のデータ量が本番よりずっと少ないことです。PostgreSQLのドキュメントは、EXPLAINの結果を、実際に試している状況と大きく違う状況に当てはめるべきではないとし、ごく小さなテーブルでの結果は大きなテーブルには当てはまらないと書いています。*1 テーブルの大きさが変わると、プランナーが別の計画を選ぶことがあるからです。検証環境では速くなったのに本番では変わらない、という食い違いを避けるには、本番に近いデータ量の環境で実行計画を取ります。
二つ目は、EXPLAINで測った時間を画面の応答時間と同じものとして扱うことです。ANALYZE付きのEXPLAINで測る時間には、結果の行を利用者の側へ送るネットワークの時間が含まれません。また、測定そのものにかかる負荷が大きくなる環境もあります。*1 SQLの改善の効果はEXPLAINで確かめ、目標の順守率は画面の応答時間で確かめる、と分けておくと、外部エンジニアと社内で判定がそろいます。
三つ目は、調査のための設定を本番に入れたままにすることです。遅いSQLの実行計画を自動でログに残すauto_explainという拡張機能では、実際の時間も記録する設定(log_analyze)をオンにすると、ログに残るかどうかにかかわらず、すべてのSQLで各段階の時間を測るようになります。これは性能に非常に大きな悪影響を与えることがあると、ドキュメントに注意書きがあります。*7 調べ終わったら設定を元に戻すことと、だれが戻すのかを、作業を始める前に決めておきます。
外部に委託するときに確認しておきたい点
外部エンジニアへの依頼は、作業名と期間で書きます。たとえば「pg_stat_statementsの合計時間の上位10本について、実行計画の取得と改善案の作成を2週間、承認した案の反映と測定を1週間」のように書いておけば、どこまでが調査で、どこからが変更なのかを双方で確かめられます。改善案には、SQLの書き換え・索引の追加・統計情報の更新のどれなのかと、変更前後の実行計画を添えてもらいます。
作業が終わったことの確かめ方は、非機能要求グレードの「性能テスト」の項目が参考になります。測定の頻度は「測定しない」「構築当初に測定」「運用中、必要時に測定可能」「運用中、定常的に測定」の4段階、確かめる機能は「確認しない」「一部の機能について、目標値を満たしていることを確認」「全ての機能について、目標値を満たしていることを確認」の3段階で示されています。*3
SQLチューニングの依頼では、目標を決めた機能すべてで満たしたことを確かめるのか、直したSQLに関係する機能だけを確かめるのかを先に決めます。作業のあとも運用中に測り続けるなら、pg_stat_statementsの記録を続け、だれがどの頻度で一覧を見るのかも決めておきます。記録は専用の関数(pg_stat_statements_reset)で消去でき、SQLごとに記録を始めた日時も残るので、変更の前後で集計の期間をそろえて比べられます。性能の不具合の数え方は「性能改善の定義と不具合の数え方」で、EXPLAINの読み方は「スロークエリの直し方」で扱っています。
まとめ:SQLチューニングで確かめたい3つの点
外部エンジニアにSQLチューニングを頼むうえで、確かめておきたい点は3つに整理できます。第一に、機能ごとに応答時間と順守率を決め、性能改善の目標を数値で示すこと。第二に、pg_stat_statementsなどで実行時間の合計と平均を集め、直す候補のSQLを一覧にして渡すこと。第三に、実行計画を取る環境、実行されたSQL文を見られる権限、変更を承認する人を社内で決めておくことです。この3点を踏まえておけば、「調べてもらったのに、どこまで直せば終わりなのかが決まらない」という事態を避けやすくなります。目標の決め方や候補の絞り込みに迷いがあれば、外部の手を借りるのも一つの選択肢です。
よくある質問
PostgreSQL以外のデータベースでも同じ進め方ができますか
目標の決め方と、作業名と期間で依頼を書く進め方は、製品が違っても使えます。SQLごとの実行時間を集める機能や、実行計画を出す命令は製品ごとに名前と設定が違うので、使っている製品の公式ドキュメントで確かめてから依頼に書きます。
統計情報は、いつ更新すればよいですか
テーブルのデータの分布を大きく変えたとき、たとえば大量のデータを一括で取り込んだあとは、ANALYZEの実行が強く勧められています。統計情報が無いか古いと、プランナーがまずい判断をして性能が落ちることがあるためです。*8 自動でANALYZEを実行する仕組み(autovacuum)が有効なら、自動で実行されることもあります。
pg_stat_statementsで記録できるSQLの数に上限はありますか
あります。記録できる数はpg_stat_statements.maxという設定で決まり、既定値は5000です。これを超える種類のSQLが実行されると、実行回数の少ないSQLの情報から捨てられます。*5 この設定はサーバーの起動時にしか変えられないので、拡張機能を有効にするときに合わせて決めておきます。
SQLチューニングの期間は、どう見積もればよいですか
候補のSQLの本数と、変更を本番に反映できる日程で決まります。調査と改善案の作成、反映と測定を分けて期間を決め、反映の期間には本番の変更の手続きにかかる日数も含めておくと、予定がずれにくくなります。
SQLチューニングを外部エンジニアに頼みたいとき
性能改善の目標の決め方や、渡す資料の整理からご相談いただけます。
Remoguとリラシクなら、リモートワークで働く社員の候補者も、業務委託で開発に加わる専門人材も探せます。
Remoguは、リモート前提で全国から即戦力のITプロ人材を調達するサービスです。リラシクは、扱う求人がすべてリモートワークのITエンジニア専門転職エージェントです。どちらもLASSICが運営しています。
出典
- *1 参考:PostgreSQL 18 Documentation「14.1. Using EXPLAIN」(https://www.postgresql.org/docs/current/using-explain.html)。出典:The PostgreSQL Global Development Group「PostgreSQL 18 Documentation」14.1 Using EXPLAIN。実行計画とプランナーの説明、14.1.3 Caveats(ANALYZE付きのEXPLAINの時間にネットワーク転送の時間が含まれないこと、測定の負荷、小さなテーブルの結果を大きなテーブルに当てはめないこと)を参照(2026年9月確認)
- *2 参考:PostgreSQL 18 Documentation「14.2. Statistics Used by the Planner」(https://www.postgresql.org/docs/current/planner-stats.html)。出典:同ドキュメント 14.2.1 Single-Column Statistics。pg_class と pg_statistic の統計情報が VACUUM・ANALYZE で更新され、近似値であることを参照(2026年9月確認)
- *3 参考:IPA「非機能要求グレード2018 項目一覧」(https://www.ipa.go.jp/archive/digital/iot-en-ci/jyouryuu/hikinou/ent03-b.html)。出典:独立行政法人情報処理推進機構(IPA)「非機能要求グレード2018」本体一括ダウンロード(ZIP)に収録の「04_項目一覧」。B.2 性能目標値(オンラインレスポンス)の小項目説明、B.2.1.1 通常時レスポンス順守率のレベル、B.4.2.1 測定頻度、B.4.2.2 確認範囲を参照(2026年9月確認)
- *4 参考:IPA「非機能要求グレード」実践セミナー 講義資料(2019年3月4日)(https://www.ipa.go.jp/archive/files/000072715.pdf)。出典:IPAセミナー@東京「非機能要求グレード」実践セミナー(2019年3月4日)講義資料。演習の想定システム要求(発注処理の通常時のオンラインレスポンスと順守率)を参照(2026年9月確認)
- *5 参考:PostgreSQL 18 Documentation「F.32. pg_stat_statements」(https://www.postgresql.org/docs/current/pgstatstatements.html)。出典:同ドキュメント F.32 pg_stat_statements。モジュールの読み込みと再起動、ビューの列(calls・total_exec_time・mean_exec_time・stats_since)、SQLの文面を見られるロール、定数の置き換え、pg_stat_statements_reset、pg_stat_statements.max を参照(2026年9月確認)
- *6 参考:PostgreSQL 18 Documentation「EXPLAIN」(https://www.postgresql.org/docs/current/sql-explain.html)。出典:同ドキュメント SQL Commands「EXPLAIN」。ANALYZE オプションで文が実際に実行されることと、BEGIN と ROLLBACK で囲む方法を参照(2026年9月確認)
- *7 参考:PostgreSQL 18 Documentation「F.3. auto_explain」(https://www.postgresql.org/docs/current/auto-explain.html)。出典:同ドキュメント F.3 auto_explain。auto_explain.log_analyze の注意(すべての文で各段階の時間を測ることによる性能への悪影響)を参照(2026年9月確認)
- *8 参考:PostgreSQL 18 Documentation「14.4. Populating a Database」(https://www.postgresql.org/docs/current/populate.html)。出典:同ドキュメント 14.4.8 Run ANALYZE Afterwards。データの分布を大きく変えたあとに ANALYZE を実行することの推奨を参照(2026年9月確認)