¿Un índice compuesto también es bueno para consultas en el primer campo?

87

Digamos que tengo una tabla con campos Ay B. Hago consultas regulares en A+ B, así que creé un índice compuesto en (A,B). ¿Las consultas en solo Atambién se optimizarán completamente mediante el índice compuesto?

Además, creé un índice A, pero Postgres todavía usa el índice compuesto solo para consultas A. Si la respuesta anterior es positiva, supongo que realmente no importa, pero ¿por qué selecciona el índice compuesto de forma predeterminada, si el Aíndice único está disponible?

Luciano
fuente
Traté de configurar una pequeña prueba para esto. En mi caso, sin embargo, el índice de dos columnas se usó solo cuando eliminé el de una sola columna, sin relación con el que se creó primero. Es interesante que si creé primero el índice de dos columnas, el plan inicial usaría un escaneo de montón de mapa de bits. Si creé el índice de una columna, luego ejecuté la consulta (escaneo de índice usado) y descarté el índice recién creado, el plan que involucra el índice de dos columnas cambió a escaneo de índice. Vea los pasos en SQLFiddle
dezso
@dezso Interesante. ¿Dónde están los costos para cada consulta?
Luciano
Costo de exploración del índice de mapa de bits: 107,98, 43 ms de tiempo de ejecución. Escaneo de índice de una columna: costo 8.69, dos columnas: 43.69. Los tiempos de ejecución no difieren significativamente (la fluctuación es mayor que la diferencia entre los dos).
dezso
@Luciano ¿Puede mostrar el explain analyzetexto y el de la consulta?
Craig Ringer

Respuestas:

88

Ciertamente lo es. Discutimos eso en gran detalle bajo esta pregunta relacionada:

El espacio se asigna en múltiplos de MAXALIGN, que normalmente es de 8 bytes en un sistema operativo de 64 bits o (mucho menos común) 4 bytes en un sistema operativo de 32 bits. Si no está seguro, verifique pg_controldata. También depende de los tipos de datos de las columnas indexadas (algunas requieren relleno de alineación) y el contenido real.

Un índice en, digamos, dos integercolumnas (4 bytes cada una) generalmente termina siendo exactamente tan grande como un índice en solo una, donde otros 4 bytes se pierden en el relleno de alineación.

En tal caso, realmente no hay inconveniente para que el planificador de consultas use un índice activado, en (a,b)comparación con un índice solo (a). Y generalmente es preferible que múltiples consultas usen el mismo índice. La posibilidad de que (o partes de ella) resida en caché (rápido) aumenta cuando se comparte.

Si ya mantiene un índice activado (a,b), entonces no tiene sentido crear otro índice solo (a), a menos que sea sustancialmente más pequeño. Lo mismo no ocurre con (b,a)vs (a). Siga el enlace en la primera línea para obtener más información al respecto.

Viniendo desde la dirección opuesta, cuando necesite un índice adicional como ese (a,b), considere colocar un índice existente solo (a), si es posible. A menudo no es posible, ya que ese es el índice de una PK o UNIQUErestricción. Desde Postgres 11, puede salirse con solo agregar ba la definición de restricción con la INCLUDEcláusula. Detalles en el manual.

O cree el nuevo índice en su (b,a)lugar para cubrir consultas solo badicionalmente. Solo para condiciones de igualdad, el orden de las expresiones de índice en los índices btree no importa. Sin embargo, lo hace cuando involucra condiciones de rango. Ver:

Existen posibles desventajas para incluir columnas adicionales en un índice, incluso si eso solo usa espacio perdido de otra manera en el relleno de alineación:

  • Cada vez que se actualiza la columna adicional, el índice ahora también necesita una actualización, lo que podría agregar costos para escribir operaciones y crear más hinchazón del índice.
  • Las actualizaciones HOT (Tupla de solo almacenamiento dinámico) en la tabla no son posibles mientras esté involucrada cualquier columna de índice.

Más sobre actualizaciones CALIENTES:

Cómo medir tamaños de objeto:

Erwin Brandstetter
fuente
1
¿Podría extender esto para decir que, si tengo un índice en la columna A, y surge la necesidad de agregar un índice compuesto (A, B), el índice A debería descartarse? Si la reutilización de un índice mejora la eficiencia de la memoria caché y (A, B) optimiza por completo, A, entonces parece que un índice adicional en A desperdiciará espacio y posiblemente ralentizará las cosas
jvans
1
@jvans: generalmente cierto, con notables excepciones y alternativas. Agregué un párrafo para abordar eso.
Erwin Brandstetter
2

Según su pregunta, tiene una tabla con los campos A y B. Si su consulta es:

SELECT * FROM [YOUR TBL]
WHERE A='XXXX'

¡Optimizer elegirá el índice Compuesto para evitar el acceso aleatorio de Extracción!

BongSey
fuente
-4

Es en el caso si solo usas primero en el predicado.

Analizará si utiliza las primeras columnas de clave compuesta y la columna sin clave de clave compuesta.

Para engañarlo, puede usar predicados ficticios como este y luego una columna sin clave:

[A, B] es su índice, [C] - otra columna

Para utilizar el índice, escriba como:

SELECT
    A,B,C,D,E
FROM 
    test
WHERE
   A=1
AND
   B=B
AND 
   C=3

... ¿por qué selecciona el índice compuesto de forma predeterminada, si el único índice A está disponible?

Utilizará el índice solo en el caso si hay uno o dos predicados [A] o [A], [B]. No lo usará en el orden [B], [A] o [A], [C]. Para poder utilizar el índice con la columna adicional [C], debe aplicar el índice ordenando predicados como [A], [B] y [C].

Farfarak
fuente
2
¿Con qué logras exactamente B=B? Creo que no logras nada, así que voy a rechazar cualquier evidencia que el optimizador no ignore
Jack Douglas
2
B=Bes efectivamente lo mismo B IS NOT NULLque parece innecesario. Ciertamente no es necesario usar un índice en (a,b).
Erwin Brandstetter