Hash Join vs Hash Semi Join


8

PostgreSQL 9.2

Sto cercando di capire la differenza tra Hash Semi Joine giusto Hash Join.

Ecco due domande:

io

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

Come si può vedere, l'unica differenza nei piani è che nel primo caso consuma hastable 7kB, ma nel secondo 37kBe che è il nodo Hash Semi Join.

Ma non capisco la differenza nelle dimensioni dell'hashtable. Il Hashnodo utilizza perfettamente lo stesso Seq Scannodo con lo stesso Filter. Perché c'è la differenza?


Hai esaminato l'output effettivo delle query? Oppure usa explain (analyze, verbose).
jjanes,

Risposte:


5

Nella prima query, solo il customer_id deve essere salvato dalla customerstabella hash, poiché questi sono gli unici dati necessari per implementare il semi-join.

Nella seconda query, tutte le colonne devono essere archiviate nella tabella hash, perché si stanno selezionando tutte le colonne dalla tabella (usando *) anziché semplicemente testare l'esistenza del customer_id.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.