У меня есть следующие таблицы и определения индекса:
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);
Почему ни один из индексов munkalap_id не используется в следующем запросе?
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
Это то же самое, даже если я добавлю фильтр:
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 байта на строку) + битовая маска NULL + выравнивание в соответствии с MAXALIGN. Наконец, неизвестный объем заполнения из-за выравнивания данных в зависимости от типов данных столбцов и их последовательности. Всего на странице 8 Кбайт не более 33 строк. (Не принимая во внимание тост.)EXPLAIN ANALYZE SELECT foo from bar
выполнить проверку с помощью фиктивной таблицы. Кроме того, фактическое пространство на диске зависит от выравнивания данных, которое будет трудно учесть, когда извлекаются только некоторые строки. Ширина строки вEXPLAIN
представляет базовую потребность в пространстве для извлеченного набора столбцов.Вы извлекаете все строки из обеих таблиц, поэтому использование сканирования по индексу не приносит никакой реальной выгоды. Сканирование индекса имеет смысл, только если вы выбираете только несколько строк в таблице (обычно менее 10% -15%).
источник
(lezarva, munkalap_id)
и он достаточно избирателен, его можно использовать. ЭтоNOT
делает это менее вероятным.