PostgreSQLの「パーティションプルーニング」を使いこなして、クエリを爆速にする話
やあ。最近、PostgreSQLのパフォーマンスチューニングの相談を受けることが増えたんだけど、その中でも「パーティションテーブルを使っているのに、なぜかクエリが遅い」というケースによく遭遇するんだ。
原因のほとんどは、「パーティションプルーニング(Partition Pruning)」が効いていないことにある。今日は、PostgreSQLが誇るこの強力な最適化機能の裏側と、現場で「ハマらない」ためのコツを、実戦的な視点で深掘りしてみようと思う。
—
パーティションプルーニングって、結局なんなの?
簡単に言うと、「検索条件に合致しないパーティションを、物理的に見に行かない」という機能だ。
例えば、数年分のログデータが月ごとにパーティション分けされているテーブルがあるとしよう。`SELECT FROM logs WHERE created_at = ‘2023-10-05’` というクエリを投げたとき、PostgreSQLは2023年10月のパーティションだけをスキャンし、他の数年分のデータは完全に無視する。
これがあるからこそ、何億行という巨大なテーブルでも現実的な時間でレスポンスが返ってくるわけだね。この「無視する」という判断を下すタイミングが、大きく分けて2種類ある。
—
1. 静的プルーニング(コンパイル時に終わらせる)
これは一番理想的なケースだ。クエリが解析された時点で、「あ、この条件なら特定のパーティションしか見なくていいや」とオプティマイザが判断する。
— 静的プルーニングが効く例
EXPLAIN SELECT FROM logs WHERE created_at = ‘2023-10-01’;
`EXPLAIN` を実行したときに、`Subplans Removed` とか、スキャン対象のパーティションが限定されているのが確認できるはずだ。これはクエリプランナーがSQLの構文解析の段階で答えを出せるから、オーバーヘッドがほぼゼロなんだ。
2. 実行時プルーニング(実行中に見極める)
問題はこっちだ。クエリの条件が複雑だったり、サブクエリや関数が含まれていて、「実行してみるまでどのパーティションが必要か分からない」というケースがある。
例えば、こんな感じのクエリだ。
— 実行時プルーニングが必要なケース
SELECT FROM logs
WHERE created_at = (SELECT max(created_at) FROM last_updates);
この場合、まずサブクエリを実行して日付を取得してから、「あ、じゃあこのパーティションが必要だな」と判断する。これが「実行時プルーニング」。静的ほど完璧ではないけれど、それでも全件走査(フルスキャン)を避けるためにPostgreSQLが頑張ってくれている証拠だ。
—
実務で「ハマる」ポイント:気をつけるべきこと
現場でよくある失敗談をシェアしておこう。ここを押さえておくだけで、君のコードの信頼性はグッと上がるはずだ。
- データ型の不一致は命取り
パーティションキーが `timestamp` 型なのに、クエリで `’2023-10-01′::text` と比較したり、暗黙の型変換が走るような書き方をすると、プルーニングが効かなくなることがある。PostgreSQLは「型が一致していないと、別の値が含まれているかもしれない」と疑うからね。型は常に厳密に合わせるのが鉄則だ。
- 関数を条件に使うなら「イコール」で
`WHERE date_trunc(‘month’, created_at) = ‘2023-10-01’` のように、パーティションキーを関数で囲んでしまうと、プランナーはプルーニングの判断ができなくなることが多い。キーそのものに対して条件を記述する癖をつけよう。
- プランナの統計情報を過信しない
データが偏っている場合、プランナが「全スキャンしたほうが速い」と誤った判断をしてプルーニングを放棄することもある。もし意図したプルーニングが動いていないなら、`EXPLAIN (ANALYZE, BUFFERS)` を取って、どこで時間を食っているか可視化するのがエンジニアの流儀だ。
—
まとめ:結局、どう向き合うか
パーティションプルーニングは「魔法」じゃない。PostgreSQLという優秀な相棒が、SQLの意図を汲み取れるように「クエリを明快に書く」ことが、結局のところ一番の近道なんだ。
複雑なクエリを書くときは、常に「PostgreSQLがどのパーティションを削ってくれるのか?」を頭の中でシミュレーションしてみてほしい。もし不安なら、すぐ `EXPLAIN` を叩く。この習慣だけで、君が書くSQLのパフォーマンスは劇的に変わるはずだよ。
何か具体的なクエリで困っていることがあったら、いつでも持ってきてくれ。一緒にデバッグしよう。現場からは以上だ!
コメント