【テクニカル・上級編】 拡張統計情報 (CREATE STATISTICS) – PostgreSQL

PostgreSQLの「隠れた目」を覚醒させる:拡張統計情報(CREATE STATISTICS)の深淵

PostgreSQLのクエリオプティマイザは、間違いなく世界で最も洗練されたエンジンの一つです。しかし、どれほど優秀なプランナであっても、提供される情報が不完全であれば誤った判断を下します。

皆さんも一度は経験があるはずです。インデックスは完璧に貼られているのに、なぜかプランナがフルスキャンを選択してしまい、現場で「なぜその実行計画になったんだ?」と頭を抱えた経験が。その原因の多くは、テーブルの統計情報が「列の独立性」という前提に縛られていることにあります。

今日は、PostgreSQLが陥りやすいこの「統計情報の罠」と、それを打破するための強力な武器である`CREATE STATISTICS`について、内部アーキテクチャの視点から掘り下げてみましょう。

—

なぜプランナは「推測」を外すのか?

標準的なPostgreSQLの統計情報(`pg_statistic`)は、基本的に列ごとのヒストグラムやMCV(Most Common Values)に依存しています。ここで問題になるのが、「複数の列間に相関関係がある場合」の計算式です。

例えば、`city`(都市)と`zip_code`(郵便番号)という2つの列があるとします。プランナはこれらを完全に独立した事象として扱い、選択率(Selectivity)を掛け合わせます。

  • `SELECT FROM addresses WHERE city = ‘Tokyo’ AND zip_code = ‘100-0001’;`

プランナは「Tokyoである確率」×「100-0001である確率」を計算します。しかし実際には、この2つは強く相関しています。結果として、プランナは「極めて稀な結果が返ってくる」と過小評価し、ネステッドループを選択して、数百万行のバッファを無駄に読み込む……という悲劇が起きるわけです。

拡張統計情報:マルチコラムの相関を紐解く

PostgreSQL 10で導入された`CREATE STATISTICS`は、まさにこの「列間の見えない繋がり」をプランナに可視化するためのものです。特に注目すべきは、以下の3つの機能です。

  • `dependencies`: 複数の列の機能的依存関係を追跡します。
  • `ndistinct`: 複数列の組み合わせにおけるユニークな値の数を推定します。
  • `mcv`: 複数列の組み合わせにおける、頻出する値のセットを直接保持します。

特に私が実務で多用するのは `mcv` リストです。これは、特定のフィルタ条件が組み合わさった時に、実際にどれくらいの行数が返ってくるかを高精度に予測できます。これがあれば、プランナは「あ、これはインデックスよりもビットマップヒープスキャンの方が効率的だ」と正しく判断できるようになります。

現場で直面する「統計情報のアンチパターン」

「とりあえず全列に統計を貼ればいいのか?」というと、それは違います。ここが熟練エンジニアの腕の見せ所です。

1. オーバーヘッドの罠: 拡張統計情報は、`ANALYZE`実行時に計算されます。列数が多く複雑な相関を指定すると、統計情報の収集時間そのものが無視できないコストになり、書き込みトランザクションに悪影響を及ぼします。
2. プランナの混乱: 統計情報を「とりあえず全部」作成すると、逆にプランナがどの統計情報を参照すべきか迷い、見積もりが不安定になるケースを観測したことがあります。必要最小限の、本当に相関が強い列の組み合わせに絞るべきです。
3. メンテナンスコスト: スキーマ変更で列が削除されると、統計オブジェクトも正しくメンテナンスしないと浮いてしまいます。

トラブルシューティングの勘所

もし本番環境で「見積もりの乖離(Cardinality Misestimation)」に悩まされたら、まずは `EXPLAIN ANALYZE` の `Actual Rows` と `Estimated Rows` を比較してください。

もしそこに100倍、1000倍の乖離があるなら、それは統計情報の欠如を疑うサインです。まずは `pg_stats_ext` を確認し、現在どのような拡張統計が設定されているか、そしてそれがクエリのフィルタリング条件と一致しているかを確認しましょう。

SELECT FROM pg_stats_ext WHERE stxrelid = ‘your_table’::regclass;

もし、それでも改善しない場合は、`mcv` の統計情報の精度(`statistics_target`)を一時的に引き上げてみるのも手です。

最後に:データベースは「対話」である

PostgreSQLは、決してブラックボックスではありません。私たちがクエリを通して「このデータにはこういう相関があるんだよ」とヒントを与えてあげれば、エンジンは期待以上のパフォーマンスで応えてくれます。

`CREATE STATISTICS`は、データベースという巨大な機械に対する、高度な「チューニングの対話」です。教科書的な知識で終わらせず、ぜひ皆さんの環境で、実行計画を眺めながら調整してみてください。その1秒のクエリ短縮の中にこそ、エンジニアとしての真の喜びがあるはずです。

さて、次はどの統計を最適化しましょうか?また現場でお会いしましょう。

コメント

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