J'ai les définitions de table et d'index suivantes:
CREATE TABLE munkalap (
munkalap_id serial PRIMARY KEY,
...
);
CREATE TABLE munkalap_lepes (
munkalap_lepes_id serial PRIMARY KEY,
munkalap_id integer REFERENCES munkalap (munkalap_id),
...
);
CREATE INDEX idx_munkalap_lepes_munkalap_id ON munkalap_lepes (munkalap_id);
Pourquoi aucun des index de munkalap_id n'est-il utilisé dans la requête suivante?
EXPLAIN ANALYZE SELECT ml.* FROM munkalap m JOIN munkalap_lepes ml USING (munkalap_id);
QUERY PLAN
Hash Join (cost=119.17..2050.88 rows=38046 width=214) (actual time=0.824..18.011 rows=38046 loops=1)
Hash Cond: (ml.munkalap_id = m.munkalap_id)
-> Seq Scan on munkalap_lepes ml (cost=0.00..1313.46 rows=38046 width=214) (actual time=0.005..4.574 rows=38046 loops=1)
-> Hash (cost=78.52..78.52 rows=3252 width=4) (actual time=0.810..0.810 rows=3253 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 115kB
-> Seq Scan on munkalap m (cost=0.00..78.52 rows=3252 width=4) (actual time=0.003..0.398 rows=3253 loops=1)
Total runtime: 19.786 ms
C'est la même chose même si j'ajoute un filtre:
EXPLAIN ANALYZE SELECT ml.* FROM munkalap m JOIN munkalap_lepes ml USING (munkalap_id) WHERE NOT lezarva;
QUERY PLAN
Hash Join (cost=79.60..1545.79 rows=1006 width=214) (actual time=0.616..10.824 rows=964 loops=1)
Hash Cond: (ml.munkalap_id = m.munkalap_id)
-> Seq Scan on munkalap_lepes ml (cost=0.00..1313.46 rows=38046 width=214) (actual time=0.007..5.061 rows=38046 loops=1)
-> Hash (cost=78.52..78.52 rows=86 width=4) (actual time=0.587..0.587 rows=87 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 4kB
-> Seq Scan on munkalap m (cost=0.00..78.52 rows=86 width=4) (actual time=0.014..0.560 rows=87 loops=1)
Filter: (NOT lezarva)
Total runtime: 10.911 ms
HeapTupleHeader
(23 octets par ligne) + masque binaire NULL + alignement selon MAXALIGN. Enfin, une quantité inconnue de remplissage en raison de l'alignement des données en fonction des types de données des colonnes et de leur séquence. Dans l'ensemble, il n'y a pas plus de 33 lignes sur une page de 8 ko dans ce cas. (Sans prendre en compte TOAST.)EXPLAIN ANALYZE SELECT foo from bar
avec une table factice de base pour vérifier. En outre, l'espace réel sur le disque dépend de l'alignement des données, ce qui serait difficile à prendre en compte lorsque seules certaines lignes sont récupérées. La largeur de ligne enEXPLAIN
représente l'espace de base requis pour l'ensemble de colonnes récupéré.Vous récupérez toutes les lignes des deux tables, il n'y a donc aucun avantage réel à utiliser une analyse d'index. Une analyse d'index n'a de sens que si vous ne sélectionnez que quelques lignes dans une table (généralement moins de 10% -15%)
la source
(lezarva, munkalap_id)
est activé et qu'il est suffisamment sélectif, il peut être utilisé. LeNOT
fait que moins probable.