Mam następujące definicje tabel i indeksów:
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);
Dlaczego żaden z indeksów na munkalap_id nie jest używany w następującym zapytaniu?
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
To samo, nawet jeśli dodam filtr:
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 bajty w wierszu) + maska NULL + wyrównanie zgodnie z MAXALIGN. Wreszcie nieznana ilość dopełnienia z powodu wyrównania danych w zależności od typów danych kolumn i ich sekwencji. W sumie w tym przypadku nie ma więcej niż 33 wierszy na stronie o wielkości 8 kb. (Nie biorąc pod uwagę TOAST.)EXPLAIN ANALYZE SELECT foo from bar
uruchomić podstawową tabelę fikcyjną w celu weryfikacji. Rzeczywiste miejsce na dysku zależy również od wyrównania danych, co trudno byłoby uwzględnić, gdy pobierane są tylko niektóre wiersze. Szerokość wiersza wEXPLAIN
oznacza podstawowe zapotrzebowanie na miejsce dla pobranego zestawu kolumn.Pobierasz wszystkie wiersze z obu tabel, więc nie ma realnych korzyści z zastosowania skanowania indeksu. Skanowanie indeksu ma sens tylko wtedy, gdy wybierasz tylko kilka wierszy z tabeli (zwykle mniej niż 10% -15%)
źródło
(lezarva, munkalap_id)
i jest on wystarczająco selektywny, możesz go użyć. ToNOT
sprawia, że mniej prawdopodobne.