PostgreSQLのパフォーマンスを極める:パーティションワイズ集約が「刺さる」瞬間
PostgreSQLで大規模データを扱う際、避けて通れないのが「集約処理の重さ」ですよね。数億行におよぶパーティションテーブルに対して`GROUP BY`を投げたとき、CPUが張り付き、ワークメモリが溢れてディスクへの退避(spill to disk)が発生し、クエリが泥沼化する……。そんな経験、一度はあるはずです。
今日は、そんな悪夢を回避するための強力な武器、「パーティションワイズ集約(Partition-wise Aggregation)」について深掘りしていこうと思います。教科書的な説明は一旦置いておいて、現場でどう振る舞い、どうチューニングすべきかという実践的な視点で語ります。
—
パーティションワイズ集約とは何か?
端的に言えば、「親テーブル全体で集約を行う前に、個々のパーティション単位で先に集約を済ませてしまう」という最適化手法です。
通常、PostgreSQLはパーティションテーブルに対する集約を、全パーティションをマージした後に実行します。しかし、パーティションワイズ集約が有効になると、プランナは各パーティションごとに部分集約を行い、その結果を最後に結合(Append)するプランを選択します。
これにより、以下の2点が劇的に改善されます。
- メモリ効率の向上: 中間結果がパーティションごとに小さく収まるため、`work_mem`を圧迫しにくい。
- 並列実行の恩恵: 各パーティションの処理を並列化(Parallel Append)と組み合わせることで、マルチコアの性能をフルに引き出せる。
—
なぜ「プランナ」が選んでくれないのか?(トラブルシューティング)
「有効なはずなのに、EXPLAINを見ると普通の集約プランになっている……」。これ、よくある相談です。パーティションワイズ集約が発動しないのには、明確な理由がいくつかあります。
1. `enable_partitionwise_aggregate`の無効化:
まずは基本ですが、PostgreSQL 11以降で導入されたこの設定値を確認してください。デフォルトでOFFになっているケースが多いです。
2. 集約関数の互換性:
使っている集約関数が「パーティションをまたいで結合できるか」が重要です。単純な`SUM`や`COUNT`なら問題ありませんが、複雑なカスタム集約や、特定の順序を前提とする関数では、プランナが安全策をとって最適化を諦めることがあります。
3. コスト見積もりの壁:
プランナは「パーティションワイズ集約によるオーバーヘッド」と「全データ一括処理」を天秤にかけます。パーティション数が少なすぎたり、各パーティションのサイズが小さすぎたりすると、「わざわざ分割して集約するコストの方が高い」と判断されます。
ここでプロのひと工夫:
もしプランナが渋るなら、`EXPLAIN (COSTS, VERBOSE)`で詳細を確認し、期待しているプランと実際のプランのコスト差を見てください。圧倒的にパーティションワイズの方が効率的なはずなのに選ばれない場合、統計情報(`ANALYZE`)が古くてカーディナリティの予測が外れていることがほとんどです。
—
現場で直面する「落とし穴」
この手法は魔法ではありません。注意点も知っておくべきです。
- メモリ消費の「分散」:
パーティション単位で集約を行うということは、同時に複数のパーティションを処理する場合、`work_mem`がパーティションの数だけ並列で消費される可能性があることを意味します。並列度(`max_parallel_workers`)の設定と`work_mem`のバランスを慎重に見極めないと、今度はメモリ不足でOOM Killerに撃たれるリスクがあります。
- ディスクI/Oのボトルネック:
パーティションワイズ集約はCPU負荷を最適化しますが、全パーティションを同時に読みに行くため、ストレージのI/O帯域を一気に食いつぶします。SSD環境ならいいですが、古いHDD構成やネットワークストレージの場合は、かえって遅延を招くこともあります。
—
最後に:チューニングは「観測」から始まる
パーティションワイズ集約を使いこなす鍵は、机上の空論ではなく「実際のデータ分布」をプランナに正しく伝えることに尽きます。
まずは `SET enable_partitionwise_aggregate = on;` を試し、クエリの実行計画がどう変化するかを観察してください。もし性能が向上するなら、それはあなたのテーブル設計が最適化の恩恵を受けやすい形になっている証拠です。
データベースエンジニアにとって、最適化は「パズル」のようなものです。PostgreSQLという強力なエンジンが、どう考えて、どう動いているのか。その内部アーキテクチャを理解すれば、クエリは必ず速くなります。
皆さんの現場でも、ぜひ一度この最適化を検証してみてください。劇的な改善が見られたときのあの快感こそ、エンジニア冥利に尽きるというものです。
それでは、また次回の深掘りでお会いしましょう。
コメント