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

PostgreSQL:¿Por qué esta consulta no usa mi índice?

Como ya te diste cuenta, el problema está relacionado con el uso de operadores que no sean iguales. Un índice solo se puede usar de manera más eficiente para las columnas más a la izquierda que se comparan entre iguales (más una condición de rango).

En tu ejemplo:

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

Puede usar el índice solo para a y b eficientemente. Eso significa que la base de datos obtiene todas las filas que coinciden con a y b condición y luego compara cada fila con las condiciones restantes.

Cuando cambias el filtro en c a iguales, obtiene (potencialmente) menos filas (solo aquellas que coinciden con a y b y c ) y luego verifica esas (menos) filas contra el d filtrar. Usar el índice es más eficiente en este caso.

En general, el planificador de consultas de PostgreSQL evalúa ambas opciones:(1) usando el índice; (2) haciendo un SeqScan. Para ambos, calcula un valor de costo:cuanto mayor es, peor es el rendimiento esperado. En consecuencia, se toma la de menor valor de costo. Así es como decide usar el índice o no, no hay un umbral fijo.

Finalmente, se escribió "más una condición de rango" arriba. Eso significa que no solo puede usar el índice de la manera más eficiente si usa signos de igual, sino también para una sola condición de rango.

Teniendo en cuenta que tiene una sola condición de rango en su consulta, le sugiero que cambie el índice de esta manera:

create index i on t (a,b,d,c);

Ahora puede usar los filtros en a y b y d eficientemente con el índice y solo necesita filtrar las filas donde c!=5 . Aunque este índice se puede usar de manera más eficiente para su consulta que el original, no significa automáticamente que PG lo usará. Depende de las estimaciones de costos. Pero pruébalo.

Finalmente, si esto no es lo suficientemente rápido, y el valor 5 estás usando en la expresión c!=5 es constante, podría considerar un índice parcial:

 create index i on t (a,b,d)
        where c!=5;

También podría hacer eso con todas las demás columnas, si los valores con los que las compara son constantes.

Referencias: