Eu tenho as seguintes definições de tabela e índice:
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);
Por que nenhum dos índices em munkalap_id é usado na consulta a seguir?
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
É o mesmo, mesmo se eu adicionar um filtro:
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 bytes por linha) + máscara de bit nula + alinhamento de acordo com MAXALIGN. Por fim, uma quantidade desconhecida de preenchimento devido ao alinhamento dos dados, dependendo dos tipos de dados das colunas e sua sequência. No total, não há mais de 33 linhas em uma página de 8 kb neste caso. (Não tendo BRINDE em conta.)EXPLAIN ANALYZE SELECT foo from bar
uma tabela fictícia básica para verificar. Além disso, o espaço real no disco depende do alinhamento dos dados, o que seria difícil de considerar quando apenas algumas linhas são recuperadas. A largura da linha emEXPLAIN
representa o requisito básico de espaço para o conjunto recuperado de colunas.Você está recuperando todas as linhas de ambas as tabelas, portanto, não há benefício real usando uma varredura de índice. Uma varredura de índice só faz sentido se você estiver selecionando apenas algumas linhas de uma tabela (geralmente menos de 10% a 15%)
fonte
(lezarva, munkalap_id)
e for seletivo o suficiente, poderá ser usado. ONOT
torna isso menos provável.