Hash Join vs Hash Semi Join

8

PostgreSQL 9.2

J'essaie de comprendre la différence entre Hash Semi Joinet juste Hash Join.

Voici deux requêtes:

je

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

Comme on peut le voir, la seule différence dans les plans est que dans le premier cas, l'hastable consomme 7kB, mais dans le second 37kBet que le nœud l'est Hash Semi Join.

Mais je ne comprends pas la différence dans la taille de la table de hachage. Le Hashnœud utilise parfaitement le même Seq Scannœud ayant le même Filter. Pourquoi y a-t-il la différence?

St.Antario
la source
Avez-vous regardé la sortie réelle des requêtes? Ou, utilisez explain (analyze, verbose).
jjanes

Réponses:

5

Dans la première requête, seul le customer_id doit être enregistré customersdans la table de hachage, car ce sont les seules données nécessaires pour implémenter la semi-jointure.

Dans la deuxième requête, toutes les colonnes doivent être stockées dans la table de hachage, car vous sélectionnez toutes les colonnes de la table (en utilisant *) plutôt que de simplement tester l'existence de customer_id.

jjanes
la source