2 つのテーブルの結合に利用可能なプランが3 つあります。

  • 入れ子になったループの結合:テーブルは、その他の結合されたテーブルの行ごとに 1 回スキャンされます。
  • マージソート結合:各テーブルは、結合の開始前に結合属性でソートされます。 次に、これら 2 つのテーブルが並行してスキャンされ、一致した行が結合されて結合行が形成されます。
  • ハッシュ結合:テーブルがスキャンされ、その結合属性がハッシュテーブルにロードされます。 テーブルの結合属性はハッシュキーとして使用されます。 次に、その他の結合されたテーブルがスキャンされ、その結合属性がハッシュキーとして使用されて、最初のテーブルから一致した行が検索されます。

次のテーブルは、プランナーが指定されたタイプの結合プランを使えるようにするために使用するオプティマイザヒントを示しています。

表 1. 結合のヒント
ヒント 説明
USE_HASH(table [...]) テーブルにハッシュ結合を使用します。
NO_USE_HASH(table [...]) テーブルにハッシュ結合を使用しません。
USE_MERGE(table [...]) テーブルにマージソート結合を使用します。
NO_USE_MERGE(table [...]) テーブルにマージソート結合を使用しません。
USE_NL(table [...]) テーブルに入れ子になったループ結合を使用します。
NO_USE_NL(table [...]) テーブルに入れ子になったループ結合を使用しません。

次の例では、pgbench_branches テーブルと pgbench_accounts テーブルでの結合に USE_HASH ヒントが使用されています。 クエリプランは、pgbench_branches テーブルの結合属性からハッシュテーブルを作成してハッシュ結合を有効にすることを示しています。

EXPLAIN SELECT /*+ USE_HASH(b) */ b.bid, a.aid, abalance FROM pgbench_branches b, pgbench_accounts a WHERE b.bid = a.bid;

                                    QUERY PLAN
-----------------------------------------------------------------------------------
 Hash Join  (cost=21.45..81463.06 rows=2014215 width=12)
   Hash Cond: (a.bid = b.bid)
   ->  Seq Scan on pgbench_accounts a  (cost=0.00..53746.15 rows=2014215 width=12)
   ->  Hash  (cost=21.20..21.20 rows=20 width=4)
         ->  Seq Scan on pgbench_branches b  (cost=0.00..21.20 rows=20 width=4)
(5 rows)

その後、NO_USE_HASH(a b) ヒントは、プランナーにハッシュテーブル以外のアプローチを使用するように強制します。 結果はマージ結合です。

EXPLAIN SELECT /*+ NO_USE_HASH(a b) */ b.bid, a.aid, abalance FROM pgbench_branches b, pgbench_accounts a WHERE b.bid = a.bid;

                                          QUERY PLAN
-----------------------------------------------------------------------------------------------
 Merge Join  (cost=333526.08..368774.94 rows=2014215 width=12)
   Merge Cond: (b.bid = a.bid)
   ->  Sort  (cost=21.63..21.68 rows=20 width=4)
         Sort Key: b.bid
         ->  Seq Scan on pgbench_branches b  (cost=0.00..21.20 rows=20 width=4)
   ->  Materialize  (cost=333504.45..343575.53 rows=2014215 width=12)
         ->  Sort  (cost=333504.45..338539.99 rows=2014215 width=12)
               Sort Key: a.bid
               ->  Seq Scan on pgbench_accounts a  (cost=0.00..53746.15 rows=2014215 width=12)
(9 rows)

最後に、USE_MERGE ヒントは、プランナーにマージ結合の使用を強制します。

EXPLAIN SELECT /*+ USE_MERGE(a) */ b.bid, a.aid, abalance FROM pgbench_branches b, pgbench_accounts a WHERE b.bid = a.bid;

                                          QUERY PLAN
-----------------------------------------------------------------------------------------------
 Merge Join  (cost=333526.08..368774.94 rows=2014215 width=12)
   Merge Cond: (b.bid = a.bid)
   ->  Sort  (cost=21.63..21.68 rows=20 width=4)
         Sort Key: b.bid
         ->  Seq Scan on pgbench_branches b  (cost=0.00..21.20 rows=20 width=4)
   ->  Materialize  (cost=333504.45..343575.53 rows=2014215 width=12)
         ->  Sort  (cost=333504.45..338539.99 rows=2014215 width=12)
               Sort Key: a.bid
               ->  Seq Scan on pgbench_accounts a  (cost=0.00..53746.15 rows=2014215 width=12)
(9 rows)

この 3 つのテーブルの結合の例では、プランナーは pgbench_branches テーブルと pgbench_history テーブルでハッシュ結合を実行し、次に pgbench_accounts テーブルで以前の結合の結果のハッシュ結合を実行します。

EXPLAIN SELECT h.mtime, h.delta, b.bid, a.aid FROM pgbench_history h, pgbench_branches b, pgbench_accounts a WHERE h.bid = b.bid AND h.aid = a.aid;

                                       QUERY PLAN
----------------------------------------------------------------------------------------
 Hash Join  (cost=86814.29..123103.29 rows=500000 width=20)
   Hash Cond: (h.aid = a.aid)
   ->  Hash Join  (cost=21.45..15081.45 rows=500000 width=20)
         Hash Cond: (h.bid = b.bid)
         ->  Seq Scan on pgbench_history h  (cost=0.00..8185.00 rows=500000 width=20)
         ->  Hash  (cost=21.20..21.20 rows=20 width=4)
               ->  Seq Scan on pgbench_branches b  (cost=0.00..21.20 rows=20 width=4)
   ->  Hash  (cost=53746.15..53746.15 rows=2014215 width=4)
         ->  Seq Scan on pgbench_accounts a  (cost=0.00..53746.15 rows=2014215 width=4)
(9 rows)

ヒントを使用して、マージソート結合とハッシュ結合の組み合わせを強制して、プランを変更できます。

EXPLAIN SELECT /*+ USE_MERGE(h b) USE_HASH(a) */ h.mtime, h.delta, b.bid, a.aid FROM pgbench_history h, pgbench_branches b, pgbench_accounts a WHERE h.bid = b.bid AND h.aid = a.aid;

                                            QUERY PLAN
--------------------------------------------------------------------------------------------------
 Hash Join  (cost=152583.39..182562.49 rows=500000 width=20)
   Hash Cond: (h.aid = a.aid)
   ->  Merge Join  (cost=65790.55..74540.65 rows=500000 width=20)
         Merge Cond: (b.bid = h.bid)
         ->  Sort  (cost=21.63..21.68 rows=20 width=4)
               Sort Key: b.bid
               ->  Seq Scan on pgbench_branches b  (cost=0.00..21.20 rows=20 width=4)
         ->  Materialize  (cost=65768.92..68268.92 rows=500000 width=20)
               ->  Sort  (cost=65768.92..67018.92 rows=500000 width=20)
                     Sort Key: h.bid
                     ->  Seq Scan on pgbench_history h  (cost=0.00..8185.00 rows=500000 width=20)
   ->  Hash  (cost=53746.15..53746.15 rows=2014215 width=4)
         ->  Seq Scan on pgbench_accounts a  (cost=0.00..53746.15 rows=2014215 width=4)
(13 rows)