【実務・中級編】 ハッシュ結合 – PostgreSQL

なぜPostgreSQLは「ハッシュ結合」を愛するのか?―現場で役立つ内部構造のハナシ

「PostgreSQLのパフォーマンスがいまいちだな……」そう思って `EXPLAIN ANALYZE` を叩いたとき、真っ先に目に入るのが結合(Join)の方式ですよね。

Nested Loop、Merge Join、そして今日解説するHash Join。
特にデータ量が増えてくると、PostgreSQLは好んでこの「ハッシュ結合」を選択します。なぜこれほどまでに優秀なのか、そしてどこに落とし穴があるのか。現場の知見を交えて深掘りしてみましょう。

—

1. ハッシュ結合の仕組み:直感的な理解

ハッシュ結合を一言で言うなら、「一方を丸ごとメモリにぶち込んで、辞書引きする」という作戦です。

1. Buildフェーズ(ハッシュテーブル構築):
結合条件の小さい方のテーブルをスキャンし、結合キーをハッシュ関数にかけます。その結果を元にメモリ上にハッシュテーブルを作ります。これが「辞書」の役割を果たします。
2. Probeフェーズ(探索):
もう一方のテーブルをスキャンしながら、各行の結合キーを同じハッシュ関数にかけます。その結果をさっき作った「辞書」に照らし合わせ、一致する行をすかさず引っ張り出します。

Nested Loopが「片方のテーブルの1行ごとに、もう片方を全走査して探す(=時間がかかる)」のに対し、ハッシュ結合は「辞書引き」なので計算量はほぼO(N+M)。これが爆速の理由です。

—

2. 実践的な例:こんな時に選ばれる

例えば、数百万件の注文データ(`orders`)と、数万件のカテゴリマスタ(`categories`)を結合するとしましょう。

EXPLAIN ANALYZE
SELECT o.id, c.name
FROM orders o
JOIN categories c ON o.category_id = c.id;

PostgreSQLのオプティマイザは、ここで`categories`をメモリに乗せる「ハッシュテーブル」として選びます。小さい方をメモリに置くのが鉄則だからです。

ここで注意!「work_mem」という名の地雷

ここで現場のエンジニアとして一番伝えたいのが、`work_mem`の設定です。

もしハッシュテーブルがメモリ(`work_mem`)に入り切らないとどうなるか?PostgreSQLはディスクへ溢れ出します(これを「バケットの流出」と呼びます)。こうなると、せっかくのハッシュ結合がディスクI/Oの嵐に巻き込まれ、Nested Loopより遅くなることだってあります。

アドバイス:
`EXPLAIN ANALYZE`の出力を見てください。
`Batches: 1` なら理想的ですが、`Batches: 2` 以上になっていたり、`Disk: xxxkB` と表示されていたら、そのクエリはメモリ不足で苦しんでいます。その場合は、セッション単位で `SET work_mem = ’64MB’;` のように一時的に引き上げてテストしてみてください。劇的に改善することがありますよ。

—

3. いつハッシュ結合を疑うべきか?

「ハッシュ結合は最強!」と思われがちですが、実は苦手なケースもあります。

  • 不等号結合(非等価結合):

`JOIN ON a.val > b.val` のような場合、ハッシュ関数は使えません。このときはNested LoopやMerge Joinが選ばれます。

  • ソート済みの結果が欲しいとき:

ハッシュ結合はハッシュ化するため、結果の順序はバラバラです。もしその後に `ORDER BY` が続くなら、Merge Joinの方がトータルコストが安いケースがあります。

—

まとめ:現場で活かすための3ステップ

1. まずは `EXPLAIN ANALYZE` を見る習慣をつける。
「Hash Join」という文字だけでなく、その下の「Batches」と「Disk」の文字に注目する。
2. `work_mem` を意識する。
サーバー全体のメモリを食い過ぎない範囲で、重いバッチ処理があるセッションだけ調整する勇気を持つ。
3. オプティマイザを信じつつ、疑う。
データ分布が偏っていると、たまにオプティマイザが「ハッシュ結合」を過信して選んでしまうことがあります。そんな時はインデックスを見直し、統計情報(`ANALYZE`)を更新してあげるのが、エンジニアの腕の見せ所です。

ハッシュ結合は、PostgreSQLが誇る強力な武器です。その特性さえ理解していれば、DBの挙動が手に取るようにわかるようになりますよ。

さて、次は「Merge Joinがなぜ特定の条件下で最強なのか」について話しましょうか。……と、その前に、まずは手元の `EXPLAIN` 結果を眺めてみてください。きっと新しい発見があるはずです。

コメント

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