統計情報の「嘘」と付き合う:PostgreSQLクエリチューニングの深淵
PostgreSQLのオプティマイザは、常に「統計情報」という名の地図を頼りに実行計画を描きます。しかし、その地図が古かったり、解像度が低かったりするとどうなるか。当然、最適だと思っていたはずのクエリが、フルスキャンという名の奈落へ突き落とされることになります。
大規模データセットを扱う現場において、`ANALYZE`の運用は単なるメンテナンス作業ではありません。これは、データベースという「生き物」の認識を、現実に同期させ続けるための極めて高度な儀式です。
今日は、教科書にはあまり書かれていない、現場で培った「統計情報管理の勘所」について少し深く掘り下げてみましょう。
1. 「デフォルトの自動ANALYZE」は、大規模環境では時に毒となる
PostgreSQLには`autovacuum`による自動`ANALYZE`がありますが、数億行を超える巨大テーブルでこれを無条件に信頼するのは危険です。
なぜなら、デフォルトの閾値(`autovacuum_analyze_scale_factor` = 0.1)は、テーブルが大きくなればなるほど「更新されるまで放置される期間」を際限なく延ばしてしまうからです。1億行のテーブルで1000万行更新されるまで待っていたら、その間の実行計画はもはや使い物になりません。
現場の指針:
大規模テーブルに対しては、一律の設定を諦めましょう。`ALTER TABLE`で個別に`autovacuum_analyze_scale_factor`を小さく設定し、さらに「更新の絶対数」でトリガーを引くように調整する。これが、統計情報の鮮度を保つための最小の防衛線です。
2. 統計情報の「粒度」をハックする
デフォルトの統計情報収集(`default_statistics_target`)は100ですが、複雑な相関関係を持つカラムに対しては、これでは力不足です。しかし、全カラムのターゲットを上げれば、今度は`ANALYZE`にかかるコストが激増し、システム全体のCPUを焼き尽くすことになります。
ここでの最適解は「必要な箇所だけを精密にする」こと。
— 特定カラムだけ解像度を上げる(統計情報の粒度を最大1000まで引き上げる)
ALTER TABLE orders ALTER COLUMN user_id SET STATISTICS 500;
特に、カーディナリティが高いIDカラムや、データ分布が偏っているフラグカラムに対してはこのチューニングが劇的に効きます。逆に、頻繁に更新されるタイムスタンプ系カラムに高い数値を設定すると、`ANALYZE`のコストが爆上がりするので注意が必要です。
3. 「統計情報のロック」という禁じ手と、その活用法
たまに遭遇するのが、「統計情報が更新された瞬間に、実行計画が劇的に悪化する」というケースです。典型的なのは、特定の時間帯にデータ分布が極端に偏るバッチ処理の最中などですね。
こういう時は、`pg_statistic`の更新を一時的に止める、あるいは`ANALYZE`を制御下に置く必要があります。
- 統計情報の保護: 重要なクエリが安定しているなら、あえてその時の統計情報を「神聖化」し、自動更新のタイミングを制御する運用も一つの戦略です。
- 手動ANALYZEの戦略的配置: `autovacuum`に任せるのではなく、バッチ処理の直後に明示的に`ANALYZE`を叩く。シンプルですが、これが最も予測可能性の高い運用です。
4. パフォーマンスへの影響を最小化するために
`ANALYZE`を実行すると、サンプリングのためにテーブルを読み込みます。これが大規模なインデックスの不整合や、キャッシュの入れ替えを誘発することがあります。
もし本番環境で`ANALYZE`の負荷が無視できないレベルであれば、`pg_prewarm`を併用するか、あるいは負荷の低い時間帯に`VACUUM ANALYZE`を分割して実行するスクリプトを自作するのもエンジニアとしての腕の見せ所です。
最後に:統計情報は「推測」であることを忘れない
結局のところ、オプティマイザが導き出す実行計画はあくまで「推測」です。どれだけ`ANALYZE`を完璧に回しても、データ分布が複雑すぎてオプティマイザが読み切れないケースは必ずあります。
そんな時、`EXPLAIN (ANALYZE, BUFFERS)`の出力を見て、「おや、推定行数と実際の行数がこれほど乖離しているのか」とニヤリとできるか。そこから`CREATE STATISTICS`を使って、カラム間の相関関係(多変量統計)をデータベースに学習させられるか。
データベースのチューニングは、計算機との対話です。統計情報の数字を鵜呑みにせず、現場のデータの「揺らぎ」を常に意識する。そんな視点を持てば、あなたのデータベースはもっと速く、もっと賢く動いてくれるはずです。
さて、今日はどのテーブルの統計情報が「嘘」をついているか、覗きに行ってみませんか?
コメント