大規模テーブルの「統計情報」でハマる前に。ANALYZEのサンプリングを攻略しよう
やあ。最近、PostgreSQLのパフォーマンスチューニングに頭を悩ませているメンバーが増えてきたね。
「クエリが急に遅くなった」「実行計画がめちゃくちゃになった」……そんな時、真っ先に疑うべきなのが統計情報(Statistics)だ。PostgreSQLのオプティマイザは、この統計情報を頼りに「どのインデックスを使うか」「どの結合順序が最適か」を判断している。
でも、数億行あるような巨大なテーブルに対して、毎回全行スキャンする `ANALYZE` を実行していたら、それだけで本番環境のCPUやI/Oを食い尽くしてしまうよね。
そこで今日は、PostgreSQLの「統計情報収集のサンプリング手法」について、現場の知恵を共有しようと思う。
—
そもそも、ANALYZEはどうやって統計を取っているのか?
`ANALYZE` を実行すると、PostgreSQLはテーブル全体をなめるわけじゃない。デフォルトでは、設定された割合(`default_statistics_target` に関連するパラメータ)に基づいて、テーブルの一部をランダムに抽出(サンプリング)して統計を推定しているんだ。
この「一部だけ見て全体を知る」という仕組み、実は理にかなっている。少量のデータで分布さえ正確に掴めれば、実行計画の精度は十分担保できるからね。
サンプリングの設定:何が鍵になるのか?
統計情報の精度をコントロールしたい時にいじるのが、`default_statistics_target` だ。
— 現在の統計取得ターゲットを確認
SHOW default_statistics_target;
デフォルトは `100` になっていることが多いはずだ。この数値が大きいほど、サンプリングする行数が増え、統計の精度は上がる。逆に小さくすれば、`ANALYZE` は爆速になるけど、データ分布の歪みに弱くなる。
現場で「あえて設定を変える」ケース
例えば、特定のカラムが極端に偏ったデータ(「A」が9割で「B」が1割、みたいなケース)を持っている場合、デフォルトのサンプリングでは「B」の存在を見落とすことがある。その結果、オプティマイザが「Bはほとんどないはずだ」と判断を誤り、フルスキャンを選択して爆死する……なんてのは、よくある悲劇だ。
そういう時は、特定のカラムだけターゲットを引き上げてやろう。
— 特定のカラムだけ統計精度を上げる(最大1000まで)
ALTER TABLE orders ALTER COLUMN status SET STATISTICS 500;
こうすることで、テーブル全体の設定はいじらずに、重要なカラムだけピンポイントで精度を担保できる。これ、かなり使えるテクニックだよ。
—
注意点:統計情報収集の「時間」と「精度」のトレードオフ
実務で一番怖いのは、「統計情報が古くて実行計画がバグる」ことと、「統計情報収集が重すぎて本番に影響が出る」ことの板挟みだ。
大規模なテーブルに対して「よし、精度を上げよう!」と全カラムの `STATISTICS` を `1000` に上げると、`ANALYZE` の実行時間が数倍に跳ね上がる。本番環境の負荷を考えたら、無闇に上げるのはNGだ。
おすすめの運用アプローチ
1. まずはデフォルトで様子を見る:ほとんどのケースはこれで十分だ。
2. 実行計画が怪しいクエリだけ特定する:`EXPLAIN ANALYZE` を実行して、「推定行数(rows)」と「実際の行数(actual rows)」の乖離を確認しよう。
3. 乖離が激しいカラムだけチューニングする:先ほど紹介した `ALTER TABLE … SET STATISTICS` を適用する。
4. それでもダメなら、インデックスやテーブル構成を見直す:統計の問題ではなく、物理的なデータ配置の問題かもしれないからね。
—
最後に:統計情報の「鮮度」も忘れずに
統計情報がどんなに正確でも、データが更新されまくっていたら意味がないよね。PostgreSQLの `autovacuum` が動いているか確認するのは基本中の基本だ。
大規模なバッチ処理で一気にデータを突っ込んだ直後は、必ず手動で `ANALYZE` を叩くクセをつけておこう。
— 大量更新の直後に実行
ANALYZE VERBOSE orders;
`VERBOSE` をつければ、どの程度のデータをサンプリングしたのか、どのくらい時間がかかったのかがログに出る。一度自分の環境で流してみて、「あ、これくらいの負荷なら許容範囲だな」という感覚を掴んでおくのが、優秀なエンジニアへの第一歩だ。
統計情報は、データベースの「目」だ。この目が曇らないようにケアしてあげるだけで、クエリは驚くほど速くなる。ぜひ、今日の仕事から意識してみてくれ。
それじゃ、また現場で!
コメント