Joining Relations Hints v10
When two tables are to be joined, there are three possible plans that may be used to perform the join.
- Nested Loop Join – A table is scanned once for every row in the other joined table.
- Merge Sort Join – Each table is sorted on the join attributes before the join starts. The two tables are then scanned in parallel and the matching rows are combined to form the join rows.
- Hash Join – A table is scanned and its join attributes are loaded into a hash table using its join attributes as hash keys. The other joined table is then scanned and its join attributes are used as hash keys to locate the matching rows from the first table.
The following table lists the optimizer hints that can be used to influence the planner to use one type of join plan over another.
Hint | Description |
---|---|
USE_HASH(table [...]) | Use a hash join for table . |
NO_USE_HASH(table [...]) | Do not use a hash join for table . |
USE_MERGE(table [...]) | Use a merge sort join for table . |
NO_USE_MERGE(table [...]) | Do not use a merge sort join for table . |
USE_NL(table [...]) | Use a nested loop join for table . |
NO_USE_NL(table [...]) | Do not use a nested loop join for table . |
Examples
In the following example, the USE_HASH
hint is used for a join on the pgbench_branches
and pgbench_accounts
tables. The query plan shows that a hash join is used by creating a hash table from the join attribute of the pgbench_branches
table.
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)
Next, the NO_USE_HASH(a b)
hint forces the planner to use an approach other than hash tables. The result is a merge join.
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)
Finally, the USE_MERGE
hint forces the planner to use a merge join.
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)
In this three-table join example, the planner first performs a hash join on the pgbench_branches
and pgbench_history
tables, then finally performs a hash join of the result with the pgbench_accounts
table.
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)
This plan is altered by using hints to force a combination of a merge sort join and a hash join.
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)