> [!NOTE] Hash Join > <table> > <tr> > <td width="25%"><img src="assets/ex_hashjoin.png"></td> > <td>A join strategy designed for large, unsorted datasets. The engine builds a hash table in memory (using <code>work_mem</code>) from the smaller 'inner' relation. It then scans the 'outer' relation, probing the hash table for matches. High memory efficiency for equijoins.</td> > </tr> > </table> > > ```sql > -- Joining two tables using a hash table > EXPLAIN (ANALYZE, COSTS, BUFFERS, VERBOSE) > SELECT * FROM animals a > JOIN species s ON a.species_id = s.id; > ``` > > ![HashJoin Plan Tree](assets/plan_tree_op_hash_join.svg) > > ```text > Hash Join (cost=1.11..223.61 rows=10000 width=42) (actual time=0.012..1.014 rows=10000 loops=1) > Output: a.id, a.name, a.species_id, a.created_at, s.id, s.name, s.diet_type > Inner Unique: true > Hash Cond: (a.species_id = s.id) > Buffers: shared hit=75 > -> Seq Scan on public.animals a (cost=0.00..174.00 rows=10000 width=27) (actual time=0.003..0.291 rows=10000 loops=1) > Output: a.id, a.name, a.species_id, a.created_at > Buffers: shared hit=74 > -> Hash (cost=1.05..1.05 rows=5 width=15) (actual time=0.006..0.006 rows=5 loops=1) > Output: s.id, s.name, s.diet_type > Buckets: 1024 Batches: 1 Memory Usage: 9kB > Buffers: shared hit=1 > -> Seq Scan on public.species s (cost=0.00..1.05 rows=5 width=15) (actual time=0.002..0.002 rows=5 loops=1) > Output: s.id, s.name, s.diet_type > Buffers: shared hit=1 > Planning: > Buffers: shared hit=256 > Planning Time: 0.348 ms > Execution Time: 1.207 ms > ``` > > ![Hash Join measured plan performance signature](assets/trace_op_hash_join.svg) > > <table> > <tr> > <td rowspan="2" width="25%"><img src="assets/ex_hash.svg"></td> > <td><b>Performance</b></td><td>High performance for large datasets; prefers cases where the inner relation fits in <code>work_mem</code>.</td> > </tr> > <tr><td><b>Cost</b></td><td><code>build cost + probe cost + cpu_operator_cost * rows joined</code></td></tr> > </table>