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

Por que a consulta mais natural (ou seja, usando INNER JOIN (em vez de LEFT JOIN)) é muito lenta


(conforme orientado, estou colocando parte do meu comentário em uma resposta, pois resolveu o problema)

Converta as expressões EXISTS em expressões IN.

Isso funciona melhor neste caso porque a consulta agora será efetivamente avaliada "de dentro para fora", começando com a consulta que contém seu fator mais limitante:a pesquisa de pesquisa de texto completo. Essa consulta retornará um pequeno conjunto de linhas que podem ser pesquisadas diretamente na chave primária da consulta externa (WHERE x in (SELECT X...)) em vez de chamar a consulta "interna" uma vez por valor de a consulta externa (ou para todos os valores no seu caso original, se eu estiver lendo corretamente). O método EXISTS aqui resulta em loops aninhados (uma avaliação de uma consulta para cada valor em outra) versus o método IN usando junções de hash (um método de execução muito mais eficiente em muitos, se não na maioria dos casos.

Observe que, com o método EXISTS, existem quatro loops aninhados que são executados com cada um executando pelo menos 3.000 vezes. Esse custo se soma. Embora não seja uma comparação direta, você pode tratar os loops aninhados como faria com os loops FOR no código do aplicativo:cada vez que você invoca um loop interno, sua estimativa de big-O aumenta uma ordem de magnitude:O(n) para O(n^ 2) para O(n^3), etc.

Hash Join é mais como um mapa, onde duas matrizes são percorridas ao mesmo tempo e uma operação é executada em ambas. Isto é aproximadamente linear (O(n)). Pense nestes sendo aninhados como aditivos, então iria O(n) para O(2n) para O(3n), etc.

Sim, sim, eu sei que não é exatamente a mesma coisa, mas o ponto é que ter vários loops aninhados geralmente indica um plano de consulta lento e comparar os dois estilos big-O facilita o reconhecimento, acredito. em>

Loops aninhados e EXISTS não são ruins, por si só, mas para a maioria dos casos onde há uma condição de filtro base que acaba afetando tudo (por exemplo, a pesquisa de texto completo na pergunta), uma expressão IN (ou, em algumas casos, um JOIN adequado) produz um plano muito mais eficiente.