sql >> Base de Datos >  >> RDS >> PostgreSQL

Por qué la consulta más natural (es decir, usar INNER JOIN (en lugar de LEFT JOIN)) es muy lenta

(como se indica, estoy poniendo parte de mi comentario en una respuesta, ya que resolvió el problema)

Convierta las expresiones EXISTS en expresiones IN.

Esto funciona mejor en este caso porque la consulta ahora se evaluará de manera efectiva desde "adentro hacia afuera", comenzando con la consulta que contiene su factor más limitante:la búsqueda de texto completo. Esa consulta devolverá un pequeño conjunto de filas que se pueden buscar directamente en la clave principal de la consulta externa (DONDE x en (SELECCIONAR X...)) en lugar de llamar a la consulta "interna" una vez por valor de la consulta externa (o para todos los valores en su caso original, si lo estoy leyendo correctamente). El método EXISTS aquí da como resultado bucles anidados (una evaluación de una consulta para cada valor en otro) frente al método IN que usa combinaciones hash (un método de ejecución mucho más eficiente en muchos casos, si no en la mayoría).

Tenga en cuenta que con el método EXISTS, hay cuatro bucles anidados que se ejecutan cada uno al menos 3000 veces. Ese costo se suma. Si bien no es una comparación directa, puede tratar los bucles anidados como lo haría con los bucles FOR en el código de la aplicación:cada vez que invoca un bucle interno, su estimación de O grande aumenta en un orden de magnitud:O(n) a O(n^ 2) a O(n^3), etc.

Hash Join es más como un mapa, donde se recorren dos matrices al mismo tiempo y se realiza una operación en ambas. Esto es aproximadamente lineal (O(n)). Piense en estos anidados como aditivos, por lo que iría de O(n) a O(2n) a O(3n), etc.

Sí, sí, sé que no es exactamente lo mismo, pero el punto es que tener múltiples bucles anidados generalmente indica un plan de consulta lento y comparar el estilo de dos grandes O hace que sea más fácil de reconocer, creo.

Los bucles anidados y EXISTS no son malos per se, pero para la mayoría de los casos donde hay una condición de filtro base que finalmente afecta todo (por ejemplo, la búsqueda de texto completo en la pregunta), una expresión IN (o, en algunos casos, un JOIN adecuado) produce un plan mucho más eficiente.