高コストなクエリ
最終更新日 2024年05月04日(土)
Table of Contents
高コストなクエリは、実行が低速、ディスクの読み書きが実行時間の多くを占める、のいずれかまたは両方に当てはまるデータベースクエリです。そのようなクエリは、Heroku Postgres データベースのパフォーマンスの問題の最も一般的な原因です。
高コストなクエリを最適化すれば、アプリケーションのパフォーマンスと全体的な応答時間を大幅に改善できます。
Premier または Signature Success Plan の Heroku Enterprise の顧客は、Customer Solutions Architecture (CSA) チームに、このトピックに関する詳細なガイダンスを要求できます。ここでエキスパートコーチングセッションについて学習するか、または Salesforce の担当者にお問い合わせください。
高コストなクエリの確認
データベースの高コストなクエリは data.heroku.com で確認できます。一覧からデータベースを選択して Diagnose
(診断) タブに移動します。
Diagnose
(診断) タブは Essential または Shield 層のデータベースでは利用できません。
最も時間がかかる、最も呼び出しが頻繁、などのカテゴリ別にクエリが表示され、最適化の最も有力な候補が一番上に表示されます。クエリの実行頻度と通常の所要時間を示すグラフがクエリごとに表示されます。高コストなクエリのデータは、最大で過去 7 日分を取得できます。
低速なパラメータ値の特定
低速なクエリでバインドパラメータ ($1
) またはクエリパラメータ (?
) が使用されている場合、これらのパラメータの値は Diagnose
(診断) タブに表示されません。同じクエリでも、パラメータの値によってパフォーマンスに大きく差が付く可能性があります。
低速なクエリのログを有効にすると、(2 秒以上かかる) 最も低速なクエリとそのパラメータが Heroku によってアプリケーションのログに出力され、特に低速なパラメータ値の特定に役立ちます。ログ記録アドオンを使用して、このような低速なクエリのログデータを検索できます。
たとえば、次のようになります。
Jun 26 08:49:40 issuetriage app/postgres.29339: [DATABASE] [41-1] LOG: duration: 2406.615 ms execute <unnamed>: SELECT "issues".* FROM "issues" WHERE "issues"."repo_id" = $1 AND "issues"."state" = $2 ORDER BY created_at DESC LIMIT $3 OFFSET $4
Jun 26 08:49:40 issuetriage app/postgres.29339: [DATABASE] [41-2] DETAIL: parameters: $1 = '1348', $2 = 'open', $3 = '20', $4 = '760'
このクエリの実行所要時間は 2.4 秒でした。パラメータ値は、repo_id
が 1348
、state
が open
、クエリの LIMIT
が 20
、クエリの OFFSET
が 760
でした。この情報を EXPLAIN ANALYZE
と共に使用することで、特定のパラメータの組み合わせが低速である理由をプロファイリングできます。
高コストなクエリの原因
高コストなクエリの最も一般的な原因には、以下のものがあります。
- 適切なインデックスがないため、サイズの大きいテーブルで検索が低速になる
- 未使用のインデックスが原因で
INSERT
、UPDATE
、DELETE
の各操作が低速になる - 非効率的なスキーマに起因する不適切なクエリ
- クエリの設計が非効率的
- データベースのサイズが大きいことやロック競合の多さが原因で (論理バックアップ)に使用される)
COPY
操作が低速になる
高コストなクエリの解決策
ここでは、高コストなクエリの修正に役立つガイドラインをいくつか示します。
- (pg:psql) 経由で)
EXPLAIN ANALYZE
を実行して、クエリの実行時間の大半を占めている処理を突き止めます。- たとえば、大きなテーブルのシーケンシャルスキャンは、多くの場合、悪い兆候です。効率的なインデックスによってクエリのパフォーマンスは大幅に向上します。インデックスの戦略を考えるときは、部分インデックスなど、Postgres のすべてのテクニックを検討してください。
heroku pg:diagnose
を実行して未使用のインデックスを特定します。不要なインデックスがあれば削除します。- データベースを最新バージョンにアップグレードします。Postgres のパフォーマンスは、リリースのたびにほぼ確実に向上します。
- 大規模なデータベースでは、日常のディザスタリカバリーの目的には Heroku の継続的保護の使用を優先します。自動
pg:backups
プランがあれば削除し、pg:backups
はデータの抽出または移行のみに使用します。 - 小規模なデータベースの場合、低速な論理バックアップの原因はロック競合の結果である可能性があります。
- Heroku pg-extras の
pg:outliers
を使用して、実行時間の多くを占めているクエリを突き止めます。
統計のリセット
Postgres の内部統計をリセットして、変更の効果を見やすくすることができます。