【実務・中級編】 ヒストグラム統計 – PostgreSQL

「なぜか遅いクエリ」を救うヒストグラムの正体:統計情報を味方につける話

現場で働いていると、「さっきまでは爆速だったのに、急にクエリが遅くなった」なんてトラブルに遭遇すること、ありますよね。

実行計画(`EXPLAIN ANALYZE`)を見てみると、PostgreSQLが実際とはかけ離れた行数を見積もっていて、本来なら使われるはずのインデックスが無視されていた……なんて経験、一度はあるはずです。

その犯人の多くは、「統計情報の不一致」です。特に、範囲検索を多用するシステムで頼りになるのが、今回解説する「ヒストグラム統計」。こいつを理解すると、PostgreSQLのオプティマイザとの対話がぐっと楽になりますよ。

—

ヒストグラムって、そもそも何?

PostgreSQLがクエリを実行するとき、プランナは「どの道順でデータを拾うのが一番速いか」を計算します。その時、最も重要な判断材料になるのが「この条件に一致するデータは何行あるか?」という見積もり(選択率)です。

例えば、「`age > 30` のユーザーを抽出したい」という時、PostgreSQLはテーブル全体をスキャンしなくても、「だいたいこれくらいの行数だろう」と予測して実行計画を立てます。この予測に使われるのが、列データの分布をバケット(箱)で表現したヒストグラムです。

デフォルトでは、各列につき100個のバケットが用意されます。値が密集しているところは細かく、バラついているところは粗く表現することで、データ分布の「山と谷」を把握しているわけです。

—

実践:どうやってチューニングに活かすのか?

基本的には、`ANALYZE`コマンドを実行すればPostgreSQLがいい感じにヒストグラムを作ってくれます。でも、実務ではこれだけじゃ足りないことも多いんです。

1. 統計情報の精度を上げる

もし、ある特定のカラム(例えば `status_code` や `category` など)に対して範囲検索や絞り込みを多用するなら、デフォルトの100バケットでは精度が足りないことがあります。そんなときは、列ごとの統計情報の粒度を上げてやりましょう。

— 統計情報のバケット数をデフォルトの100から300に引き上げる
ALTER TABLE orders ALTER COLUMN created_at SET STATISTICS 300;

— 反映させるためにanalyzeを実行
ANALYZE orders;

これだけで、特定カラムの見積もり精度が劇的に改善することがあります。ただし、バケット数を増やしすぎると `ANALYZE` 自体の負荷が上がるので、闇雲に大きくせず、慎重に見極めるのがコツです。

2. 見積もりがズレているか確認する

「ヒストグラムが効いていないな?」と疑ったら、`pg_stats` ビューを覗いてみてください。ここにはプランナが持っている「カンニングペーパー」がすべて載っています。

SELECT
column_name,
null_frac, — NULLの割合
n_distinct, — 推定ユニーク数
histogram_bounds — これがヒストグラム!
FROM pg_stats
WHERE tablename = ‘orders’ AND column_name = ‘created_at’;

`histogram_bounds` の中身を見て、「データの偏りに対してバケットが粗すぎないか?」をチェックする。これができるだけで、DBエンジニアとしてのレベルが一つ上がります。

—

先輩からのアドバイス:ハマりどころ

最後に、現場でよくある「ハマりポイント」を2つだけ伝授しておきます。

  • 「データの更新頻度」を忘れないこと

ヒストグラムは `ANALYZE` を実行した時点の「過去の遺産」です。大量のデータが短時間で投入・削除される環境では、いくらヒストグラムを調整しても実態と乖離します。`autovacuum` がちゃんと動いているか、あるいはバッチ処理の直後に `ANALYZE` を入れているか、確認してみてください。

  • 相関関係には弱い

ヒストグラムは基本的に「列単体」の分布しか見ていません。「`prefecture_id` がAで、かつ `age` が20〜30」のような、列をまたいだ条件の相関関係までは考慮できないことが多いです。こういう場合は、`CREATE STATISTICS` を使って「多変量統計」を活用するステップへ進む必要があります。

—

まとめ

ヒストグラムは、PostgreSQLという「優秀だけど時に頑固なプランナ」に、現場のデータのリアルを伝えるための大切なツールです。

「クエリが遅い」と感じたら、まずは `EXPLAIN ANALYZE` を叩いて、予測行数(rows)と実測行数(actual rows)を見比べてみてください。そこに大きな乖離があるなら、ヒストグラムがあなたの助けを待っています。

データベースチューニングは、データと対話する作業です。ぜひ、今日から統計情報を眺める癖をつけてみてください。きっと今よりもっと、PostgreSQLと仲良くなれますよ。

それでは、また現場で!

コメント

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