PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

PostgreSQL:Por que esta consulta não está usando meu índice?


Como você já percebeu, o problema está relacionado ao uso de operadores diferentes de iguais. Um índice só pode ser usado com mais eficiência para as colunas mais à esquerda que são comparadas por igual (mais uma condição de intervalo).

No seu exemplo:
create index i on t (a,b,c,d);
where a=1 and b=11 and c!=5 and d<8;

Ele pode usar o índice apenas para a e b eficientemente. Isso significa que o banco de dados busca todas as linhas que correspondem ao a e b condição e, em seguida, verifica cada linha em relação às condições restantes.

Quando você altera o filtro em c para igual, ele busca (potencialmente) menos linhas (somente aquelas que correspondem a a e b e c ) e, em seguida, verifica essas (menos) linhas em relação ao d filtro. Usar o índice é mais eficiente neste caso.

Em geral, o planejador de consultas do PostgreSQL avalia as duas opções:(1) usando o índice; (2) fazer um SeqScan. Para ambos, calcula um valor de custo — quanto maior, pior é o desempenho esperado. Consequentemente, leva aquele com o menor valor de custo. É assim que ele decide usar o índice ou não, não há limite fixo.

Finalmente, está escrito "mais uma condição de intervalo" acima. Isso significa que ele pode não apenas usar o índice da maneira mais eficiente se você estiver usando sinais de igual, mas também para uma única condição de intervalo.

Considerando que você tem uma única condição de intervalo em sua consulta, sugiro alterar o índice assim:
create index i on t (a,b,d,c);

Agora ele pode usar os filtros em a e b e d eficientemente com o índice e só precisa filtrar as linhas onde c!=5 . Embora esse índice possa ser usado de forma mais eficiente para sua consulta do que o original, isso não significa automaticamente que o PG o usará. Depende das estimativas de custo. Mas dá-lhe uma chance.

Finalmente, se isso não for rápido o suficiente e o valor 5 você está usando na expressão c!=5 é constante, você pode considerar um índice parcial:
 create index i on t (a,b,d)
        where c!=5;

Você também pode fazer isso com todas as outras colunas, se os valores com os quais você as compara forem constantes.

Referências: