Eu tenho um monte de tabelas que se parecem vagamente com isso:
CREATE TABLE table1(id INTEGER PRIMARY KEY, t1c1 INTEGER, t1c2 INTEGER);
CREATE TABLE table2(id INTEGER PRIMARY KEY, t1 INTEGER REFERENCES table1(id), t2c1 INTEGER);
E eu faço muitas junções onde estou tentando filtrar na tabela unida para obter coisas da primeira tabela, assim:
SELECT t1c1
FROM table1
JOIN table2 ON table2.t1 = table1.id
WHERE t2c1 = 42;
Quando vou escrever índices para uma tabela, olho para as colunas que são usadas na cláusula WHERE e construo índices para satisfazê-las. Então, para esta consulta, eu acabaria escrevendo um índice como este:
CREATE INDEX ON table2 (t2c1);
E esse índice é pelo menos elegível para uso nessa consulta.
Minha pergunta é que, se eu escrever um índice assim:
CREATE INDEX ON table2 (t2c1, t1);
O índice será usado como um índice de cobertura para ajudar o JOIN na consulta acima? Devo alterar minha estratégia de escrita de índice para cobrir colunas de chave estrangeira?
Depende. O Postgres tem varreduras "somente índice" como método de acesso ao índice , não há "índices de cobertura" per se - até o Postgres 10.
Começando com o Postgres 11 índices de cobertura verdadeiros com
INCLUDE
colunas estão disponíveis. Entrada de blog de Michael Paquier apresentando o recurso:Resposta relacionada com exemplo de código:
Dito isso, o índice
CREATE INDEX ON table2 (t2c1, t1);
faz todo o sentido para a consulta que você demonstra. Ele pode ser usado para uma varredura somente de índice se pré-condições adicionais forem atendidas, ou pode ser usado em uma varredura de índice de bitmap ou em uma varredura de índice simples. Relacionado:JOIN
condições eWHERE
condições são quase completamente equivalentes no Postgres. Eles certamente podem usar índices da mesma maneira. Você pode reescrever sua consulta:Com este equivalente:
A primeira forma é obviamente preferível, no entanto. Mais fácil de ler.
Por que "quase" equivalente? (Não faz diferença para a consulta simples em mãos.)
Relacionado:
Não é provável na consulta acima. Este é um problema complexo enganador com os resultados baseados nas estimativas e seletividade das duas condições,
Essencialmente, você deseja lançar ambos os ambientes (contagens de linhas) para que ambas as condições tenham mais ou menos seletividade. E se você obtiver um loop aninhado, desejará aumentar a quantidade bruta até que esse não seja mais o método de junção mais viável.
Agora verifique o plano.
Agora crie o índice composto,
E verifique o plano novamente,
Você pode soltar as chaves e tal para descobrir qual forma ele prefere
ou
Em última análise, embora isso seja muito trabalhoso, sugiro começar com
E otimizar apenas se isso não for suficiente.
Você também pode desabilitar opções específicas do planejador para ver se outro plano é realmente mais rápido ou mais lento e, em seguida, procurar corrigi-lo, mas isso também pode ser muito trabalhoso.