Heroku Postgres のパフォーマンス分析
最終更新日 2024年03月27日(水)
Table of Contents
パフォーマンス分析は、Heroku Postgres の可視性スイートです。これを使用すると、データベースのパフォーマンスを監視して、潜在的な問題を診断できます。次の複数のコンポーネントから構成されています。
高コストのクエリ
低いデータベースパフォーマンスの主な原因は、クエリが最適化されていないことです。最も高コストのクエリの一覧 (data.heroku.com から入手できます) は、データベースで最も時間がかかるクエリを識別して理解するのに役立ちます。詳細は、「高コストなクエリ」の記事を参照してください。
ログ記録
アプリケーションまたはフレームワークがデータベースアクセスのログを出力する場合、Heroku のログストリームからそれらのログを取得できます。
$ heroku logs -t
データベースサービス自体からログを表示するには、heroku logs
を -p postgres
プロセスタイプオプションと共に使用して、Postgres からのログだけを表示します。
$ heroku logs -p postgres -t
Heroku Postgres のログ文についての詳細は、「Heroku Postgres のログ文とよくあるエラーを理解する」を参照してください。
pg:diagnose
pg:diagnose
は、データベースのパフォーマンスの分析と最適化に役立つ、多数の有用なヘルスおよび診断チェックを実行します。チームメイトや Heroku サポートと共有できるレポートが生成されます。
何らかの変更を行う前に、データベースやアプリケーションへの影響を慎重に検討してください。
pg:diagnose
は shield
プランではサポートされていません。
$ heroku pg:diagnose --app sushi
Report 1234abc… for sushi::HEROKU_POSTGRESQL_MAROON_URL
available for one month after creation on 2014-07-03 21:29:40.868968+00
GREEN: Connection Count
GREEN: Long Queries
GREEN: Long Transactions
GREEN: Idle in Transaction
GREEN: Indexes
GREEN: Bloat
GREEN: Hit Rate
GREEN: Blocking Queries
GREEN: Sequences
GREEN: Unlogged Tables
GREEN: Table Transaction ID Wraparound
GREEN: Database Transaction ID Wraparound
GREEN: Schema Count
GREEN: Load
GREEN: CPU Burst
チェック: 接続数
各 Postgres 接続には、メモリが必要であり、データベースプランには、受け入れられる接続数に制限があります。使用している接続が多すぎる場合は、PgBouncer などの接続プーラーの使用か、RAM の量が多いより大きなプランへの移行を検討してください。
チェック: 長時間実行クエリ、長時間トランザクション、トランザクション内部での待ち状態
長時間実行クエリおよびトランザクションは、自動バキュームを妨げ、フォロワーを遅らせる肥大化の問題を起こす可能性があります。これらのクエリやトランザクションでの報告しきい値は 1 分 (60 秒) です。
また、データにロックが作成され、このため他のトランザクションが実行できなくなります。pg:kill
で長時間実行クエリを強制終了することを検討してください。
idle in transaction
であるバックエンドは、COMMIT;
または ROLLBACK
のどちらかを通じてクライアントがトランザクションを終了するまで待機するバックエンドです。クライアントが誤って切断されると、バックエンドがこの状態のままになる場合があります。開いたままになった場合は、pg:kill --force
を使用して終了できます。
チェック: インデックス
インデックスチェックには、3 つのクラスのインデックスが含まれます。
Never Used Indexes (使用歴のないインデックス) は、(最後の手動データベース統計の更新)から) 使用されていません。これらのインデックスは通常、フォロワーで使用されている場合以外は、破棄しても問題ありません。
Low Scans, High Writes (低スキャン、高書き込み) インデックスは、使用されているが、書き込みボリュームに比べて頻度が高くありません。インデックスは、すべての書き込みで更新されるので、高書き込みテーブルで特にコストが大きくなります。これらのインデックスによって得られるパフォーマンスの向上に対して、書き込み速度の低下のコストを考慮してください。
Seldom used Large Indexes (めったに使用されない大きなインデックス) は、それほど使用されていませんが、ディスク上とキャッシュ (RAM) 内の両方で大きな領域を占めています。これらのインデックスは、アプリケーションにとって引き続き重要である場合があります。たとえば、定期的なジョブや頻度の低いトラフィックパターンで使用されている場合があります。
インデックスの使用状況は、クエリを受信するデータベースでのみ追跡されます。読み取りにフォロワーを使用している場合、このチェックではフォロワーに対する使用が明らかにならず、不正確になる可能性があります。
チェック: 肥大化
Postgres は MVCC を使用しているため、古いバージョンの更新または削除された行がその場で変更されるのではなく、非表示になります。通常の操作では、autovacuum プロセスが行われ、非同期的にこれらを消去します。ただし、十分な速度で動作できなかったり、一部のテーブルが肥大化するのとを防止できなかったりする場合もあります。肥大化が高くなると、データベースが使用されなくなった行を調べるのにより多くの時間を費やすため、クエリの速度を低下し、領域を浪費し、負荷を増大させることがあります。
psql
内の VACUUM (VERBOSE, ANALYZE);
コマンドでテーブルを手動でバキュームできます。これが頻繁に発生する場合は、自動バキュームをより積極的なものにすることができます。
列統計値が含まれていない列 (json
列など) を使用するテーブルの肥大化評価計算は、必ずしも正確であるとは限りません。
チェック: ヒット率
全体的なインデックスヒット率、全体的なキャッシュヒット率、テーブルごとの個々のインデックスヒット率をチェックします。キャッシュヒット率が低いデータベースは、メモリから読み取るのではなくディスクにアクセスする必要があるため、パフォーマンスが大幅に低下します。キャッシュヒット率が低い場合はより大きなプランへ移行することを、インデックスヒット率が低い場合は適切なインデックスを追加することを検討してください。
全体的なキャッシュヒット率は、ディスクから読み取られたキャッシュされたブロックとキャッシュされていないブロックの総数に対する、Postgres バッファキャッシュからフェッチされたテーブルデータブロックの比率として計算されます。より大きなプランでは、キャッシュヒット率は低くなる場合がありますが、残りのデータが Postgres ではなく OS によってメモリ内にキャッシュされるため、パフォーマンスは一定のままになります。
全体的なインデックスヒット率は、ディスクから読み取られたキャッシュされたインデックス済みブロックとキャッシュされていないインデックスブロックの総数に対する、Postgres バッファキャッシュからフェッチされたインデックスブロックの比率として計算されます。より大きなプランでは、インデックスヒット率は低くなる場合がありますが、残りのインデックスデータが Postgres ではなく OS によってメモリ内にキャッシュされるため、パフォーマンスは一定のままになります。
テーブルあたりの個々のインデックスヒット率は、テーブルに対するシーケンシャルスキャンとインデックススキャンの合計と比較した、テーブルに対するインデックススキャンの比率として計算されます。
チェック: クエリのブロック
一部のクエリは、他のクエリが実行しないようにするロックをかけることがあります。通常、これらのロックはすばやく取得して解放されるため、問題は発生しません。ただし、異常な状況では、一部のクエリは、長時間保持された場合に重大な問題を引き起こすため、ロックをかけることがあります。pg:kill
を使用してクエリを強制終了することを検討してください。
チェック: シーケンス
このコマンドは、関連付けられたシーケンスが存在する 32 ビット integer
(int4 ともいう) 列を調べ、32 ビット int の最大値に近づいている列を報告します。オーバーフローを回避するために、報告された列を 64 ビット bigint
(int8 ともいう) 列に移行します。このような移行の例が alter table products alter column id type bigint;
です。列の型の変更は、特に大きなテーブルでは、高コストの操作になる場合があります。移行計画を用意するようにしてください。
複合インデックスは別にして、64 ビットシステムでの整列のために Heroku Postgres で bigint
列より integer
列を優先させる必要はありません。
このチェックは、integer
(int4) 列の数が 100 を超えている場合はスキップされます。
チェック: ログに記録されないテーブル
このチェックでは、UNLOGGED
として作成されたテーブルを探します。ログに記録されないテーブルは、高速データロードに使用できますが、先行書き込みログ (WAL) に書き込まれません。これらのテーブルに書き込まれたデータは、継続的保護の対象とされません。. データは高可用性スタンバイまたはフォロワーデータベースに複製されることもないため、メンテナンスが行われたときに、データ損失につながります。データ損失を防ぐには、テーブルが大きい場合に、ログに記録されるテーブルにデータをバッチで移動します。テーブルが小さい場合は、ALTER TABLE <table> SET LOGGED
を使用して、ログに記録されないテーブルをログに記録されるテーブルに変更します。
チェック: テーブルトランザクション ID ラップアラウンド、データベーストランザクション ID ラップアラウンド
これらのチェックは、個々のテーブルまたはデータベースが、トランザクション ID ラップアラウンドにどれだけ近づいているかを判断します。トランザクション ID ラップアラウンドとは、頻繁に更新されるテーブルに自動バキューム操作がついていけないために発生するまれなシナリオです。これらのテーブルでは、そのテーブル (またはデータベース) のトランザクション ID がラップアラウンドしてデータ損失が発生するおそれがあります。トランザクション ID ラップアラウンドを防ぐために、Postgres では、この問題が解決されるまでクラスター全体で新しい書き込みを防止するため、可用性に影響を与えます。これらのチェックでは、50% を超えるトランザクション ID 領域が使用された場合、テーブルおよびデータベース名を返します。
チェック: スキーマ数
このチェックは、データベース内のスキーマの数をカウントします。スキーマの数が 19 を超える場合は黄色の警告を、スキーマの数が 50 を超える場合は赤色の警告を報告します。スキーマの数が多いと、Postgres のパフォーマンスや、正常な論理バックアップを取得する機能に影響を与える場合があります。保持するスキーマの数が 50 を超えないようにすることをお勧めします。
チェック: 負荷
データベース上の負荷が高くなる理由には、肥大化、CPU 集約的クエリ、インデックスの作成、データベース上の多すぎるアクティビティなど多数あります。アクセスパターンを確認し、プロセッサーが強力なより大きなプランへの移行を検討してください。
チェック: CPU バースト
CPU バーストのチェックは、standard-0
、premium-0
、private-0
、shield-0
の各プランにのみ適用されます。
バースト可能な vCPU パフォーマンスを備えた Heroku Postgres プランでは、使用率が最大 20% のベースラインを超えると、CPU リソースの「バケット」を使用します。このチェックは、次のものを返します。
GREEN
大量のバースト可能なリソースが使用可能な場合。アクションは必要ありません。YELLOW
リソース使用率がベースラインを超え、現在バーストしている場合。リソース使用率を下げることが必要な場合があります。RED
バースト可能なリソースが枯渇し、ベースラインへのパフォーマンス低減が近づいているか、または現在行われている場合。Heroku Postgres プランのアップグレードを含め、パフォーマンスの低下を防ぐためのアクションが必要です。
統計のリセット
Postgres の内部統計をリセットして、変更の効果を見やすくすることができます。