【実務・中級編】 統計情報の精度(default_statistics_target) – PostgreSQL

「クエリがなぜか遅い……」
「EXPLAIN ANALYZEを見ると、見積もり行数(rows)と実際の行数が桁違いにズレている……」

PostgreSQLを触っていると、一度は必ずぶち当たる壁ですよね。インデックスも貼ったし、クエリもシンプル。なのにプランナがとんでもない実行計画を選んでしまう。

そんな時、真っ先に疑うべきなのが「統計情報の精度」です。今日は、縁の下の力持ちならぬ、クエリプランナの「目」とも言えるパラメータ『`default_statistics_target`』について、現場の知見を交えて深掘りしてみましょう。

—

そもそも、プランナは何を見て判断しているのか?

PostgreSQLのプランナは、超優秀な参謀です。でも、彼が持っている情報は「統計情報」という名の「要約レポート」だけなんですよ。

テーブルの全データを毎回スキャンしていたら、クエリの実行なんて一生終わりません。だから、`ANALYZE`コマンドを実行して、各列のデータの分布をサンプリングして記録しておくんです。

この「どれくらい細かくサンプリングするか」を決めているのが `default_statistics_target` です。デフォルト値は「100」。この数値が高いほど、ヒストグラムのバケット数が増え、データの偏り(スキュー)を正確に把握できるようになります。

—

なぜデフォルトの「100」で足りないのか?

「じゃあ、この値を大きくすれば最強じゃないか!」と思うかもしれません。確かに精度は上がります。でも、世の中そんなに甘くない。

1. ANALYZEが遅くなる: 統計情報を集めるためのサンプリングコストが増大します。
2. システムカタログが太る: 統計情報自体もデータです。`pg_statistic` テーブルが肥大化し、メモリを圧迫します。

実務で僕がよく遭遇するのは、「データの分布が極端に偏っている列」に対して、デフォルトの100では太刀打ちできないケースです。例えば、ECサイトの「注文ステータス」のようなカラム。99%が「完了」で、残りの1%に「キャンセル」や「保留」が混ざっている場合、プランナは「キャンセル」の方も「完了」と同じような頻度で発生すると勘違いして、インデックスを使わずにフルスキャンを選択して爆死することがあります。

—

実践:統計情報をチューニングする手順

もし特定のクエリの行数見積もりが明らかにズレているなら、まずはその列の統計精度を上げてみましょう。全体をいじるのではなく、「特定の列だけ」ピンポイントで上げるのが、僕らプロの流儀です。

1. 現状の確認(まずはここから)

EXPLAIN ANALYZEで、見積もり(rows)と実際の行数(actual rows)を見比べます。

EXPLAIN ANALYZE SELECT FROM orders WHERE status = ‘cancelled’;
— rows=100000 くらいで見積もっているのに、実際は 10 だったりする場合、要注意。

2. 特定の列の統計精度を上げる

テーブル全体ではなく、問題の列に対してのみ設定を変更します。

— status列の統計精度を100から500に引き上げる
ALTER TABLE orders ALTER COLUMN status SET STATISTICS 500;

3. 再度アナライズ

設定を変えただけでは反映されません。必ず`ANALYZE`を叩いて統計情報を更新させます。

ANALYZE orders;

これだけで、プランナの「目」がぐっと良くなります。これで実行計画が最適化されるはずです。

—

先輩からのアドバイス:やりすぎは禁物

この設定、便利すぎて何でもかんでも数値を上げたくなる気持ちはわかります。でも、一つだけ注意点を。

「とりあえず全部500にしておこう」という雑な設定は、百害あって一利なしです。

統計情報を更新する際のCPU負荷が増えるだけでなく、プランナが計算するコストのバリエーションが増えすぎて、かえって実行計画が安定しなくなることもあります。

基本は「デフォルト(100)」で運用し、どうしても行数見積もりがズレてパフォーマンスに悪影響が出ている「特定の列」に対してのみ、300や500といった値を適用する。これが、大規模データベースを安定運用するための鉄則です。

—

まとめ

  • 統計精度はクエリプランナの命綱: `default_statistics_target` はデータの分布を正しく理解させるための設定。
  • ピンポイントで調整せよ: 全体ではなく、`ALTER TABLE … SET STATISTICS` で問題の列を狙い撃ちする。
  • 最後は必ずANALYZE: これを忘れると、設定はただの「おまじない」で終わります。

PostgreSQLは、こうやって細部まで手をかけてあげると、驚くほど素直に、そして爆速で応えてくれるデータベースです。皆さんの現場のクエリも、ぜひ統計情報の視点で見直してみてください。

また次回の記事で、より深いチューニングの世界でお会いしましょう!

コメント

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