【実務・中級編】 パーティションワイズ結合 – PostgreSQL

その「巨大結合」、パーティションで劇的に速くできるかも?「パーティションワイズ結合」の極意

やあ!今日も元気にクエリと格闘してるかな?

最近、PostgreSQLのパフォーマンスチューニングの相談を受ける中で、「データが数億行を超えたあたりから、JOINがどうしても重くなる」という話をよく聞くんだ。インデックスも貼った、`ANALYZE`もかけた、でもまだ遅い。そんなとき、もし君がパーティショニングを導入しているなら、ぜひ確認してほしい機能がある。

それが「パーティションワイズ結合(Partition-wise Join)」だ。

教科書的な説明だと「同じパーティションキーを持つテーブル同士を、パーティション単位で結合する機能」なんて書かれるけど、これ、現場で使いこなすと「あ、こんなに速くなるの?」ってくらい劇的な差が出ることがあるんだよね。今日はその「実戦的な使い方」を伝授するよ。

—

そもそも、何が起きているのか?

通常、PostgreSQLは結合を行う際、まずテーブル全体を対象に考えて結合アルゴリズム(Hash JoinとかNested Loopとか)を組み立てる。でも、パーティション化された巨大なテーブル同士を結合する場合、PostgreSQLが「大きなテーブル全体」を一度にメモリに乗せようとして四苦八苦したり、無駄なスキャンが発生したりすることがある。

パーティションワイズ結合は、要するに「大きな戦いを、小さな戦いに分割して各個撃破する」戦術なんだ。

「Aテーブルのパーティション1」と「Bテーブルのパーティション1」を先に結合する。次に「パーティション2」同士を結合する……といった具合に、小さな塊ごとに処理を完結させる。これにより、メモリの消費量も抑えられるし、並列処理の恩恵も受けやすくなるんだ。

実践!どうやって有効にするか

実は、PostgreSQL 11以降、この機能はかなり進化していて、条件さえ揃えばオプティマイザが自動的に判断してくれることが多い。でも、「あれ、効いてないな?」という時は、設定の確認が必要だ。

まずは、ここをチェックしてほしい。

— 現在の設定を確認
SHOW enable_partitionwise_join;

これが `off` になっていたら、迷わず `on` にしよう。ただし、これにはメモリを多く消費するリスクもあるから、本番環境でいきなり変えるときは、ステージングで実行計画(`EXPLAIN`)を取るのを忘れずにね。

コードで見る「恩恵」のポイント

例えば、ECサイトの注文履歴(`orders`)と注文明細(`order_items`)が、どちらも `created_at` で月ごとにパーティション分割されているとしよう。

— 理想的なクエリの形
SELECT o.id, i.product_id
FROM orders o
JOIN order_items i ON o.id = i.order_id
WHERE o.created_at >= ‘2023-01-01’ AND o.created_at < '2023-02-01'; この時、`EXPLAIN` を叩いてみてほしい。もし効いていれば、プランのどこかに `Partitioned Hash Join` のような記述が出てくるはずだ。

ここで一つ、注意点!

パーティションワイズ結合を成功させるには、「パーティションの定義が完全に一致していること」が絶対条件だ。

  • 両方のテーブルでパーティションキーが同じか?
  • パーティションの切り方が同じ(例:両方とも月次)か?

ここがズレていると、PostgreSQLは「あ、これ別々に計算しても意味ないな」と判断して、通常の結合にフォールバックしてしまう。設計段階から「JOINのペアになるテーブルのパーティション戦略を揃える」というのは、実はパフォーマンス設計の基本中の基本なんだよ。

先輩からのアドバイス:いつ使うべきか?

「じゃあ、何でもかんでもパーティションワイズ結合にすればいいのか?」というと、そうでもない。

  • 小規模なテーブル同士:オーバーヘッドの方が大きくなって、逆に遅くなることがある。
  • 結合条件が複雑すぎる:パーティションキーで結合できていないクエリだと、当然恩恵はゼロだ。

結局のところ、一番効くのは「数千万行を超える巨大テーブル同士の結合」で「結合条件にパーティションキーが含まれている」ケースだ。ここがハマれば、クエリの実行時間が数分から数秒に短縮されることも珍しくない。

まとめ

1. `enable_partitionwise_join` が `on` になっているか確認する。
2. `EXPLAIN` をとって、実際にパーティション単位で処理されているか確認する。
3. そもそも結合するテーブル同士のパーティション設計が「鏡写し」になっているか設計を見直す。

パフォーマンスチューニングは、魔法じゃない。こうやって地道に、データベースがどう考えて動いているかを想像して、適切な道筋を作ってあげる作業なんだ。

もし君のデータベースが「重い」と悲鳴を上げていたら、まずはこの「分割統治」の戦略を試してみてくれ。きっと、驚くような結果が待っているはずだよ。

それじゃ、また現場で会おう!何か詰まったら、いつでも聞きに来てくれよな。

コメント

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