【テクニカル・上級編】 default_statistics_targetの役割 – PostgreSQL

「なぜ、私のクエリプランはいつまで経っても的外れなのか」――default_statistics_targetが握る最適化の鍵

PostgreSQLのクエリチューニングにどっぷりと浸かっていると、誰しも一度は壁にぶつかります。インデックスは貼った、VACUUMも回した、なのにプランナはなぜかネステッドループを避けて不自然なハッシュ結合を選択し、最悪の実行計画を叩き出す……。

そんな時、多くのエンジニアはまず `EXPLAIN ANALYZE` を眺め、「見積もり行数(rows)」と「実際の行数(actual rows)」の絶望的な乖離に頭を抱えることになります。この乖離を埋めるための最後の砦、それが `default_statistics_target` です。

今回は、このパラメータが単なる「設定値」を超えて、PostgreSQLのオプティマイザの「目」としてどう機能しているのか、少し深掘りしてみましょう。

—

プランナは「確率」で動いている

まず前提として、PostgreSQLのプランナは全知全能ではありません。彼らが頼りにしているのは、`pg_statistic`(システムビューの `pg_stats`)に格納された、`ANALYZE` が収集した「要約された統計情報」だけです。

`default_statistics_target` は、この統計情報の「解像度」を決定します。デフォルトの「100」という数字、皆さんはどう捉えていますか?

  • デフォルト値(100)の意味: 最も頻繁に出現する値(MCV: Most Common Values)を最大100個記録し、ヒストグラム(分布図)を100個のバケットに分割する。
  • 何が起きているか: データ分布が極端に偏っている場合、あるいはカーディナリティ(値の種類)が非常に多いカラムにおいて、この「100」という解像度では、統計情報の「ぼやけ」が生じます。

複雑なクエリになればなるほど、このぼやけは結合演算のたびに雪だるま式に増幅されます。結果、オプティマイザは「この条件なら数件しか返らないはずだ」と誤認し、非効率な実行計画を選択してしまうわけです。

統計情報の「解像度」を上げるべきタイミング

もちろん、「とりあえず1000にしておけば安心」という安易なアプローチは避けるべきです。統計情報の収集コストは、`ANALYZE` の実行時間だけでなく、カタログの肥大化にもつながります。

私が現場で `default_statistics_target` の調整(あるいはカラム単位の `ALTER TABLE … SET STATISTICS`)を検討するのは、以下のようなシグナルを検知した時です。

  • 相関関係の欠如: 複数のカラム条件を組み合わせたクエリで、見積もりが著しく狂う。
  • ロングテールな分布: 特定の値が突出して多い一方で、残りのデータが多様な値に分散している場合、100個のバケットでは分布の「裾野」を正しく表現できません。
  • 実行計画の突然変異: データ量の増加に伴い、ある閾値を超えた瞬間にプランが急激に悪化するケース。これは統計情報がデータの実際の分布を捉えきれていないサインです。

チューニングの作法:グローバルか、ローカルか

「全カラムの統計精度を上げる」のは悪手です。PostgreSQLのカタログを無駄に圧迫するだけでなく、統計収集のオーバーヘッドが運用を阻害します。

私が推奨するのは、「問題のある箇所をピンポイントで仕留める」アプローチです。

— 該当カラムだけ精度を上げる
ALTER TABLE orders ALTER COLUMN status SET STATISTICS 500;
ANALYZE orders;

このように、結合キーやフィルタ条件として頻出するカラムに対してのみ、統計情報の解像度を引き上げます。こうすることで、全体のシステム負荷を抑えつつ、オプティマイザの判断精度を劇的に向上させることが可能です。

最後に:統計情報は「スナップショット」である

忘れてはならないのは、`default_statistics_target` をどれほど厳密に設定しても、それはあくまで「ある時点のデータの影」に過ぎないということです。

もし、アプリケーションのビジネスロジックが変わってデータの分布がガラリと変われば、以前最適だった統計精度も、ただの「古い地図」になります。統計情報をいじった後は、必ず `EXPLAIN` の見積もり精度を確認し、それが実際のワークロードに対して「妥当なコスト」として機能しているかを検証してください。

データベースエンジニアの仕事は、エンジンを完璧にチューニングすることではありません。エンジンの限界と挙動を理解し、データという生きた情報の特性に合わせて、オプティマイザに正しい地図を渡してあげること。

`default_statistics_target` を調整するということは、プランナという優秀な相棒に、より精細なメガネをかけてあげるような作業なのです。ぜひ、皆さんの環境でも、一度 `pg_stats` を覗いてみてください。そこには、クエリが遅い原因が、数字の羅列として静かに眠っているはずです。

コメント

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