本番DBサーバーから頻繁にCPU使用率が高いというアラートを受け取っています。自分でこれについて詳しく調査したいので、CPU使用率が高い期間に実行中のDBクエリを収集しました。
SELECT * FROM pg_stat_activity;
収集されたデータから、UPDATE操作で頻繁にアクセスされるテーブルが1つあることがわかりました。さらなる調査の結果、テーブルがDBで最も頻繁にアクセスされるテーブルであり、リソースを大量に消費する可能性がないことがわかりました。
以下は、そのクエリについてEXPLAINから取得した詳細です。
QUERY PLAN
-------------------------------------------------------------------------------
Update on foo_table (cost=0.00..1271.14 rows=1 width=55)
-> Seq Scan on foo_table (cost=0.00..1271.14 rows=1 width=55)
Filter: (id = 2::bigint)
(3 rows)
これまでのところ、私が持っている唯一の特定のデータは、この高いCPU使用率のトリガー操作が発生している期間です。処理に時間がかかりすぎるクエリを特定することはできませんが。
以下のクエリを試してみましたが、説得力のある統計情報が見つかりませんでした。
SELECT relname, idx_tup_fetch + seq_tup_read as TotalReads from pg_stat_all_tables WHERE idx_tup_fetch + seq_tup_read != 0 order by TotalReads;
SELECT * FROM pg_stat_all_tables ORDER BY seq_scan DESC;
何が起こっているのかを理解する方法がないので、私は無力です。たとえば、ワークロードや、索引付けに関連する問題やクエリの最適化がそれを解決するので、それは正常です。
DB仕様:サイズ:150 GB以上のCPU:8コアRAM:16 GBストレージ:スワップなしのSSD。
問題は、いくつかのテーブルのインデックス作成にありました。次のクエリを実行することで、読み取り統計でこれらのテーブルを特定できました。
SELECT relname, idx_tup_fetch + seq_tup_read as TotalReads from pg_stat_all_tables WHERE idx_tup_fetch + seq_tup_read != 0 order by TotalReads desc LIMIT 10;
pg_stat_statements を見ることができます。 shared_preload_libraries
で有効にする必要がありますが、どのステートメントが最も多くのリソースを消費するかについての優れたビューを提供します。 CPU時間を直接追跡することはありませんが、追跡された合計時間とI/O時間を見ると、通常は適切な見積もりを取得できます。
まず、9.2以降、パフォーマンスが大幅に改善されました。それ以来、監視ツールも大幅に改善されました。サポートされていないシステムのパフォーマンスの問題を調査するよりも、アップグレードに時間をかける方がおそらく意味があります。
次に、実際に問題がありますか?購入したCPUを使用してデータベースを使用することは、本質的に問題ではありません。一部の(名前のない)監視ツールがアラートを送信することも、問題があることを意味するのではなく、監視ツールが壊れているか、構成が不適切である可能性があります。 CPU使用率はどのくらいですか?最も使用頻度の高いプロセスのタイトルは何ですか?ユーザーはパフォーマンスについて不満を持っていますか?
キャプチャした特定のクエリについて、 "foo_table"にインデックスがあり、インデックスの先頭列として "id"がありますか?誰かが「id」という名前を付けることを決めた列は、おそらくインデックス化されるべきです。
Pg_stat_activityの手動検査で全体像が明らかになったかどうかわからない場合は、「auto_explain.log_min_duration」で auto_explain 拡張を使用して、遅い特定の実行をキャプチャできます。これはpg_stat_statementの優れた補完であり、特定のクエリの実行ではなく、一般的に各クエリの詳細を示します。