11.5. Combinación de múltiples índices #

Un escaneo de índice único solo puede usar cláusulas de consulta que utilicen las columnas del índice con operadores de su clase de operadores y que estén unidas con AND. Por ejemplo, dado un índice en (a, b), una condición de consulta como WHERE a = 5 AND b = 6 podría usar el índice, pero una consulta como WHERE a = 5 OR b = 6 no podría usar el índice directamente.

Afortunadamente, PostgreSQL tiene la capacidad de combinar múltiples índices (incluyendo múltiples usos del mismo índice) para manejar casos que no pueden ser implementados por escaneos de índice único. El sistema puede formar condiciones AND y OR a través de varios escaneos de índice. Por ejemplo, una consulta como WHERE x = 42 OR x = 47 OR x = 53 OR x = 99 podría desglosarse en cuatro escaneos independientes de un índice en x, y cada escaneo usaría una de las cláusulas de la consulta. Los resultados de estos escaneos se unen luego mediante un operador OR para producir el resultado. Otro ejemplo es que si tenemos índices separados en x e y, una posible implementación de una consulta como WHERE x = 5 AND y = 6 es usar cada índice con la cláusula de consulta adecuada y luego unir mediante un operador AND los resultados del índice para identificar las filas de resultado.

Para combinar múltiples índices, el sistema escanea cada índice necesario y prepara un mapa de bits (bitmap) en memoria que indica las ubicaciones de las filas de la tabla que se reportan como coincidentes con las condiciones de ese índice. Los mapas de bits se combinan luego mediante operaciones AND y OR según sea necesario por la consulta. Finalmente, se visitan y devuelven las filas reales de la tabla. Las filas de la tabla se visitan en orden físico, porque así es como está dispuesto el mapa de bits; esto significa que se pierde cualquier ordenación de los índices originales, por lo que se necesitará un paso de ordenación independiente si la consulta tiene una cláusula ORDER BY. Por esta razón, y debido a que cada escaneo de índice adicional añade tiempo extra, el planificador a veces optará por utilizar un escaneo de índice simple, incluso cuando haya índices adicionales disponibles que también podrían haberse utilizado.

En todas las aplicaciones excepto en las más sencillas, hay varias combinaciones de índices que podrían ser útiles, y el desarrollador de la base de datos debe tomar decisiones para decidir qué índices proporcionar. A veces, los índices multicolumna son mejores, pero a veces es mejor crear índices separados y confiar en la función de combinación de índices. Por ejemplo, si tu carga de trabajo incluye una mezcla de consultas que a veces involucran solo la columna x, a veces solo la columna y y a veces ambas columnas, podrías optar por crear dos índices separados en x e y, confiando en la combinación de índices para procesar las consultas que usan ambas columnas. También podrías crear un índice multicolumna en (x, y). Este índice normalmente sería más eficiente que la combinación de índices para consultas que involucran ambas columnas, pero como se discutió en Section 11.3, sería menos útil para consultas que involucran solo a y. Cuán útil será dependerá de la efectividad de la optimización del escaneo por salto del índice B-tree; si x no tiene más de varios cientos de valores distintos, el escaneo por salto hará que las búsquedas de valores específicos de y se ejecuten de manera bastante eficiente. Una combinación de un índice multicolumna en (x, y) y un índice separado en y también podría funcionar razonablemente bien. Para las consultas que involucran solo a x, se podría usar el índice multicolumna, aunque sería más grande y, por lo tanto, más lento que un índice en x solo. La última alternativa es crear los tres índices, pero esto probablemente solo sea razonable si la tabla se busca mucho más a menudo de lo que se actualiza y los tres tipos de consulta son comunes. Si uno de los tipos de consulta es mucho menos común que los demás, probablemente te conformarás con crear solo los dos índices que mejor se adapten a los tipos comunes.