Hash Join vs Hash Semi Join

8

PostgreSQL 9.2

Estoy tratando de entender la diferencia entre Hash Semi Joiny justo Hash Join.

Aquí hay dos consultas:

yo

EXPLAIN ANALYZE SELECT * FROM orders WHERE customerid IN (SELECT
customerid FROM customers WHERE state='MD');

Hash Semi Join  (cost=740.34..994.61 rows=249 width=30) (actual time=2.684..4.520 rows=120 loops=1)
  Hash Cond: (orders.customerid = customers.customerid)
  ->  Seq Scan on orders  (cost=0.00..220.00 rows=12000 width=30) (actual time=0.004..0.743 rows=12000 loops=1)
  ->  Hash  (cost=738.00..738.00 rows=187 width=4) (actual time=2.664..2.664 rows=187 loops=1)
        Buckets: 1024  Batches: 1  Memory Usage: 7kB
        ->  Seq Scan on customers  (cost=0.00..738.00 rows=187 width=4) (actual time=0.018..2.638 rows=187 loops=1)
              Filter: ((state)::text = 'MD'::text)
              Rows Removed by Filter: 19813

II

EXPLAIN ANALYZE SELECT * FROM orders o JOIN customers c ON o.customerid = c.customerid WHERE c.state = 'MD'

Hash Join  (cost=740.34..1006.46 rows=112 width=298) (actual time=2.831..4.762 rows=120 loops=1)
  Hash Cond: (o.customerid = c.customerid)
  ->  Seq Scan on orders o  (cost=0.00..220.00 rows=12000 width=30) (actual time=0.004..0.768 rows=12000 loops=1)
  ->  Hash  (cost=738.00..738.00 rows=187 width=268) (actual time=2.807..2.807 rows=187 loops=1)
        Buckets: 1024  Batches: 1  Memory Usage: 37kB
        ->  Seq Scan on customers c  (cost=0.00..738.00 rows=187 width=268) (actual time=0.018..2.777 rows=187 loops=1)
              Filter: ((state)::text = 'MD'::text)
              Rows Removed by Filter: 19813

Como se puede ver, la única diferencia en los planes es que en el primer caso, el hastable consume 7kB, pero en el segundo 37kBy que el nodo es Hash Semi Join.

Pero no entiendo la diferencia en el tamaño de la tabla hash. El Hashnodo usa perfectamente el mismo Seq Scannodo que tiene el mismo Filter. ¿Por qué hay la diferencia?

St.Antario
fuente
¿Has mirado el resultado real de las consultas? O usar explain (analyze, verbose).
jjanes

Respuestas:

5

En la primera consulta, solo el customer_id debe guardarse desde la customerstabla hash, ya que esos son los únicos datos necesarios para implementar la semiunión.

En la segunda consulta, todas las columnas deben almacenarse en la tabla hash, porque está seleccionando todas las columnas de la tabla (usando *) en lugar de solo probar la existencia del customer_id.

jjanes
fuente