【テクニカル・上級編】 手動統計情報更新 – PostgreSQL

「待てない」時の切り札:PostgreSQLの統計情報と `ANALYZE` の深い話

現場で PostgreSQL を触っていると、たまに「なぜ今の実行計画を選んだ?」と頭を抱えたくなる瞬間に遭遇しますよね。特に、大量のデータを一気に流し込んだ直後や、バッチ処理でテーブルの様相がガラリと変わった直後。

PostgreSQL のオプティマイザは優秀ですが、彼らが頼りにしているのはあくまで「統計情報」という名の過去の記憶です。自動収集(`autovacuum`)が追いつかず、記憶と現実の乖離が極限まで広がったとき、クエリプランナは平然と「全表スキャン」という名の絶望を選択します。

そんな時、我々エンジニアがとるべきアクションは一つ。「手動での `ANALYZE`」です。今日は、なぜ手動実行が必要なのか、そしてその際に何を意識すべきか、少し深掘りしてみましょう。

—

なぜ「自動」を待ってはいけないのか

デフォルトの `autovacuum` は、DBの負荷を抑えるために「控えめ」に設定されています。しかし、数千万行の `UPDATE` や `INSERT` を数分で叩き込むようなワークロードでは、自動収集のトリガー(`autovacuum_analyze_scale_factor` など)を待っている間に、クリティカルなクエリが次々とタイムアウトを起こします。

ここで重要なのは、「統計情報の鮮度=実行計画の精度」であるという点です。

`ANALYZE` を実行すると、PostgreSQL はテーブルのサンプルを読み込み、`pg_statistic`(システムカタログ)を更新します。具体的には、列ごとの値の分布、NULLの比率、そして何より重要な「MCV(Most Common Values:頻出値)」のリストを更新します。これが古いままでは、インデックスが有効かどうかの判断すら誤ることになるのです。

手動実行の作法:ただ叩けばいいわけじゃない

単に `ANALYZE table_name;` と打つのは簡単です。しかし、大規模テーブルに対してこれを実行する際、いくつか知っておくべき「現場の作法」があります。

  • サンプリングの重要性:

PostgreSQL 12以降、`ANALYZE` は非常に洗練されましたが、それでも巨大なテーブル全体をスキャンするのはCPUとI/Oの無駄です。`SET default_statistics_target` で調整されたターゲット値が適切かどうかを確認しましょう。ターゲット値が大きすぎると、`ANALYZE` 自体が重いトランザクションになってしまいます。

  • 特定の列を狙い撃つ:

テーブル全体ではなく、`ANALYZE table_name(column_a, column_b);` と指定して統計情報を更新することも可能です。頻繁に検索条件や `JOIN` のキーになる列が決まっているのであれば、これだけでも十分な効果が得られます。全列スキャンを避けることで、メンテナンス時間を劇的に短縮できるケースは多いです。

  • トランザクションの分離:

`ANALYZE` は読み取りロックしか取得しませんが、それでも巨大なテーブルに対する実行は長時間になりがちです。オンラインで実行する際は、自身のクエリでテーブルをロックしてしまわないよう、バックグラウンドでの影響を考慮した実行計画を立てるのがプロの仕事です。

パフォーマンストラブルシューティングの勘所

もし本番環境で「統計情報を更新したのに、まだ遅い!」という状況に陥ったら、以下のポイントを疑ってください。

1. 相関統計情報(Extended Statistics)の欠如:
`col_a = 1 AND col_b = 2` のような複合条件は、単なる列ごとの統計情報ではプランナが関係性を理解できません。`CREATE STATISTICS` を使って、列間の相関を明示的に収集させてください。これが効いた時の「劇的なプランの変化」は、エンジニアとして最高に興奮する瞬間です。
2. `pg_statistic` の値の劣化:
`ANALYZE` を実行しても、`statistics_target` が低すぎれば、プランナは「データの偏り」を見落とします。特定の列でプランナが分布を読み間違えているなら、その列のターゲット値を個別に引き上げてみましょう。`ALTER TABLE … ALTER COLUMN … SET STATISTICS` です。

最後に

「統計情報の更新」は地味な作業かもしれません。しかし、実行計画という名の「DBの思考プロセス」を正しく導くことは、データベースエンジニアにとっての外科手術のようなものです。

自動化に甘えず、システムが今どんなデータ分布を抱えているのかを想像する。その「感度」こそが、PostgreSQL を極めるための近道だと私は信じています。

皆さんのデータベースが、今日も最適なクエリプランを選択してくれますように。それでは、また。

コメント

タイトルとURLをコピーしました