Hash Join vs Hash Semi Join

8

PostgreSQL 9.2

Ich versuche den Unterschied zwischen Hash Semi Joinund gerecht zu verstehen Hash Join.

Hier sind zwei Fragen:

ich

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

Wie zu sehen ist, besteht der einzige Unterschied in den Plänen darin, dass im ersten Fall das Hastable verbraucht 7kB, im zweiten Fall jedoch 37kBder Knoten Hash Semi Join.

Aber ich verstehe den Unterschied in der Größe der Hashtabelle nicht. Der HashKnoten verwendet perfekt denselben Seq ScanKnoten mit demselben Filter. Warum gibt es den Unterschied?

St.Antario
quelle
Haben Sie sich die tatsächliche Ausgabe der Abfragen angesehen? Oder verwenden explain (analyze, verbose).
Jjanes

Antworten:

5

In der ersten Abfrage muss nur die customer_id aus der customersHash-Tabelle gespeichert werden , da dies die einzigen Daten sind, die zum Implementieren des Semi-Joins benötigt werden.

In der zweiten Abfrage müssen alle Spalten in der Hash-Tabelle gespeichert werden, da Sie alle Spalten aus der Tabelle auswählen (mit *) und nicht nur die Existenz der customer_id testen.

jjanes
quelle