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.