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

Impacto en el rendimiento de la vista en la función agregada frente a la limitación del conjunto de resultados

Consultas no estrictamente equivalentes

Para aclarar el contexto:

  • max(id) excluye NULL valores. Pero ORDER BY ... LIMIT 1 no.
  • NULL los valores se ordenan en último lugar en orden ascendente y primero en orden descendente. Así que un Index Scan Backward podría no encontrar el mayor valor (según max() ) primero, pero cualquier número de NULL valores.

El equivalente formal de:

SELECT max(id) FROM testview;

no es:

SELECT id FROM testview ORDER BY id DESC LIMIT 1;

pero:

SELECT id FROM testview ORDER BY id DESC NULLS LAST LIMIT 1;

La última consulta no obtiene el plan de consulta rápida. Pero lo haría con un índice con orden de clasificación coincidente:(id DESC NULLS LAST) .

Eso es diferente para las funciones agregadas min() y max() . Aquellos obtienen un plan rápido cuando se orientan a la tabla test1 directamente usando el índice PK simple en (id) . Pero no cuando se basa en la vista (o la consulta de unión subyacente directamente; la vista no es el bloqueador). Un índice que ordena valores NULL en el lugar correcto apenas tiene ningún efecto.

Nosotros saber que id en esta consulta nunca puede ser NULL . La columna está definida NOT NULL . Y la unión en la vista es efectivamente una INNER JOIN que no puede introducir NULL valores para id .
Nosotros también sepa que el índice en test.id no puede contener valores NULL.
Pero el planificador de consultas de Postgres no es una IA. (Tampoco intenta serlo, eso podría salirse de control rápidamente). Veo dos deficiencias :

  • min() y max() obtenga el plan rápido solo cuando se dirija a la tabla, independientemente del orden de clasificación del índice, se agrega una condición de índice:Index Cond: (id IS NOT NULL)
  • ORDER BY ... LIMIT 1 obtiene el plan rápido solo con el orden de clasificación del índice que coincide exactamente.

No estoy seguro de si eso podría mejorarse (fácilmente).

db<>fiddle aquí - demostrando todo lo anterior

Índices

Este índice es completamente inútil:

CREATE INDEX ON "test" ("id");

El PK en test.id se implementa con un índice único en la columna, que ya cubre todo lo que el índice adicional podría hacer por usted.

Puede haber más, esperando que se aclare la pregunta.

Caso de prueba distorsionado

El caso de prueba está demasiado lejos del caso de uso real para ser significativo.

En la configuración de prueba, cada tabla tiene 100k filas, no hay garantía de que cada valor en joincol tiene una coincidencia en el otro lado, y ambas columnas pueden ser NULL

Su caso real tiene 10 millones de filas en table1 y <100 filas en table2 , cada valor en table1.joincol tiene una coincidencia en table2.joincol , ambos están definidos NOT NULL y table2.joincol es único. Una relación clásica de uno a muchos. Debería haber un UNIQUE restricción en table2.joincol y una restricción FK t1.joincol --> t2.joincol .

Pero eso es actualmente todo retorcido en la pregunta. En espera hasta que se limpie.