11.4. Índices y ORDER BY #

Además de simplemente encontrar las filas que se devolverán en una consulta, un índice puede ser capaz de entregarlas en un orden de clasificación específico. Esto permite cumplir con la especificación ORDER BY de una consulta sin un paso de ordenación independiente. De los tipos de índice actualmente admitidos por PostgreSQL, solo B-tree puede producir salidas ordenadas; los otros tipos de índice devuelven las filas coincidentes en un orden no especificado y dependiente de la implementación.

El planificador considerará satisfacer una especificación ORDER BY ya sea escaneando un índice disponible que coincida con la especificación, o escaneando la tabla en orden físico y realizando una ordenación explícita. Para una consulta que requiere escanear una gran fracción de la tabla, es probable que una ordenación explícita sea más rápida que usar un índice porque requiere menos E/S de disco debido a que sigue un patrón de acceso secuencial. Los índices son más útiles cuando solo se necesitan recuperar unas pocas filas. Un caso especial importante es ORDER BY en combinación con LIMIT n: una ordenación explícita tendrá que procesar todos los datos para identificar las primeras n filas, pero si hay un índice que coincide con el ORDER BY, las primeras n filas se pueden recuperar directamente, sin escanear el resto en absoluto.

Por defecto, los índices B-tree almacenan sus entradas en orden ascendente con los nulos al final (el TID de la tabla se trata como una columna de desempate entre entradas que de otro modo serían iguales). Esto significa que un escaneo hacia adelante de un índice en la columna x produce una salida que satisface a ORDER BY x (o de manera más detallada, ORDER BY x ASC NULLS LAST). El índice también se puede escanear hacia atrás, produciendo una salida que satisface a ORDER BY x DESC (o de manera más detallada, ORDER BY x DESC NULLS FIRST, ya que NULLS FIRST es el valor predeterminado para ORDER BY DESC).

Puedes ajustar la ordenación de un índice B-tree incluyendo las opciones ASC, DESC, NULLS FIRST y/o NULLS LAST al crear el índice; por ejemplo:

CREATE INDEX test2_info_nulls_low ON test2 (info NULLS FIRST);
CREATE INDEX test3_desc_index ON test3 (id DESC NULLS LAST);

Un índice almacenado en orden ascendente con nulos al principio puede satisfacer tanto ORDER BY x ASC NULLS FIRST como ORDER BY x DESC NULLS LAST dependiendo de en qué dirección se escanee.

Te preguntarás por qué molestarse en proporcionar las cuatro opciones, cuando dos opciones junto con la posibilidad de escaneo hacia atrás cubrirían todas las variantes de ORDER BY. En índices de una sola columna, las opciones son de hecho redundantes, pero en índices multicolumna pueden ser útiles. Considera un índice de dos columnas en (x, y): este puede satisfacer ORDER BY x, y si escaneamos hacia adelante, o ORDER BY x DESC, y DESC si escaneamos hacia atrás. Pero podría ser que la aplicación con frecuencia necesite usar ORDER BY x ASC, y DESC. No hay forma de obtener esa ordenación a partir de un índice simple, pero es posible si el índice se define como (x ASC, y DESC) o (x DESC, y ASC).

Obviamente, los índices con ordenaciones no predeterminadas son una característica bastante especializada, pero a veces pueden producir aceleraciones tremendas para ciertas consultas. Si vale la pena mantener dicho índice depende de la frecuencia con la que utilices consultas que requieran una ordenación especial.