「見えない負荷」を可視化する:pg_stat_databaseと向き合う夜
深夜2時、オンコールのアラートで叩き起こされ、ダッシュボードの真っ赤なグラフを眺める。そんな経験、データベースエンジニアなら一度はありますよね。
「DBが遅い」と言われたとき、多くの人はまず `pg_stat_activity` を覗き、今実行されているクエリの鎖を解こうとします。もちろんそれは正しい。けれど、システム全体の健康状態、あるいは「なぜ今、ディスクIOが飽和しているのか」という根本的な問いに対する答えは、もっと高いレイヤーに隠れていることが多いんです。
今日は、PostgreSQLの統計情報の宝庫、`pg_stat_database` について少し深く掘り下げてみましょう。単なるモニタリング項目としてではなく、パフォーマンスの「予兆」を読み取るための羅列として。
—
なぜ `pg_stat_database` なのか?
個別のクエリチューニングが「外科手術」なら、`pg_stat_database` を眺めるのは「健康診断」です。
このビューは、インスタンス内の各データベース単位で蓄積された統計情報のスナップショットです。特に、`xact_commit` と `xact_rollback` の比率、そして `blks_read` と `blks_hit` のバランスは、システムの現状を饒舌に語ってくれます。
1. トランザクションの「質」を問う
`xact_commit` と `xact_rollback` を見れば、アプリケーションの挙動が一目瞭然です。
もし、特定の時間帯にロールバックが急増しているなら、それはロック競合の多発か、あるいはデッドロックの頻発を意味します。アプリケーションコードの修正が必要なサインかもしれません。単純な「トランザクション数」だけでなく、その「成功率」こそが、DBの真の負荷を理解する鍵です。
2. キャッシュヒット率の嘘と真実
`blks_hit` / (`blks_read` + `blks_hit`) で計算されるキャッシュヒット率は、誰もが気にする指標です。しかし、ここで勘違いしてはいけないのは、「ヒット率が高い=健全」ではないということ。
メモリ上に乗っている古いデータに対して無駄なスキャンを繰り返していれば、ヒット率は高くてもCPUは無駄に消費されます。逆に、インデックスの設計が甘く、物理読み込み(`blks_read`)が定常的に発生しているなら、OSのページキャッシュがどれだけ頑張っても、最終的にはディスクIOのボトルネックに行き着きます。
—
現場で役立つ「読み解き」の勘所
私がトラブルシューティングで必ず見るのは、絶対値ではなく「変化の傾き」です。
- `temp_files` と `temp_bytes` の急増:
これが積み上がっているときは、SQLのチューニング不足か、`work_mem` の設定を見直すべきタイミングです。ディスクへの書き出しが発生している以上、そのクエリは既に「鈍器」になっています。
- `conflicts`(リカバリ競合):
スタンバイサーバーを使っているなら、ここを無視してはいけません。プライマリでのVACUUM処理と、スタンバイでの長い読み取りクエリが喧嘩している証拠です。`max_standby_streaming_delay` の調整だけでは根本解決にならないことが多く、クエリの寿命やVACUUMの頻度を再考する必要があります。
- `deadlocks`:
これが増えるのは、アプリケーション側のトランザクション設計が競合している証拠。DBのパラメータをいじって解決しようとするのは下策です。アプリケーション層でのアクセス順序の整理、あるいはロック範囲の縮小を検討しましょう。
—
統計情報は「嘘をつかない」が、「文脈」を必要とする
`pg_stat_database` は非常に強力ですが、あくまで累積値です。そのため、PostgreSQLが再起動されるとリセットされますし、過去のトレンドを見るには時系列データとして蓄積(PrometheusやDatadog等へのエクスポート)が必須です。
私がいつも意識しているのは、「統計情報の背後にあるクエリの意図」を想像することです。
`blks_read` が増えたとき、「ストレージが遅い」と判断する前に、「インデックスが効いていないフルスキャンが走っていないか?」あるいは「データサイズに対して、そもそも `shared_buffers` が小さすぎないか?」と問いかける。
データベースエンジニアの仕事は、単に数値を監視することではなく、その数値が何を変えれば改善するのかという「因果関係」を特定することにあります。
—
皆さんの DB も、`pg_stat_database` を通じて語りかけているはずです。
「今のクエリ、ちょっと重いよ」「メモリが足りないよ」「ロックで待たされているよ」と。
次にダッシュボードを見たときは、数値の増減の先にある PostgreSQL の内部アーキテクチャを想像してみてください。そうすれば、きっと今まで見えなかったボトルネックの正体が見えてくるはずです。
それでは、また次回の記事で。快適なデータベース運用を。
コメント