Ich habe die folgenden Tabellen- und Indexdefinitionen:
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);
Warum wird in der folgenden Abfrage keiner der Indizes für munkalap_id verwendet?
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
Es ist das gleiche, auch wenn ich einen Filter hinzufüge:
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
pro Zeilenelement + den Zeilenkopf (23 Bytes pro Zeile) + die NULL-Bitmaske + die Ausrichtung gemäß MAXALIGN berücksichtigen. Schließlich ist ein unbekannter Auffüllbetrag aufgrund der Datenausrichtung abhängig von den Datentypen der Spalten und deren Reihenfolge. Insgesamt befinden sich in diesem Fall nicht mehr als 33 Zeilen auf einer 8-KB-Seite. (Ohne Berücksichtigung von TOAST.)EXPLAIN ANALYZE SELECT foo from bar
Überprüfung mit einer einfachen Dummy-Tabelle durchführen. Der tatsächliche Speicherplatz auf der Festplatte hängt auch von der Datenausrichtung ab. Dies ist schwer zu berücksichtigen, wenn nur einige Zeilen abgerufen werden. Die Zeilenbreite inEXPLAIN
stellt den grundlegenden Platzbedarf für den abgerufenen Satz von Spalten dar.Sie rufen alle Zeilen aus beiden Tabellen ab, sodass die Verwendung eines Index-Scans keinen wirklichen Vorteil bietet. Ein Index-Scan ist nur dann sinnvoll, wenn Sie nur wenige Zeilen aus einer Tabelle auswählen (in der Regel weniger als 10% -15%).
quelle
(lezarva, munkalap_id)
und dieser selektiv genug ist, kann er verwendet werden. DasNOT
macht das weniger wahrscheinlich.