11.4. Índices e ORDER BY #

Além de apenas encontrar as linhas a serem retornadas por uma consulta, o índice pode entregá-las em uma ordem de classificação específica. Isto permite que a especificação ORDER BY de uma consulta seja respeitada sem haver uma etapa de classificação separada. De todos os tipos de índice no momento com suporte pelo PostgreSQL, apenas B-Tree pode produzir uma saída classificada — os outros tipos de índice retornam linhas correspondentes em uma ordem não específica e dependente da implementação.

O planejador vai considerar satisfazer a especificação ORDER BY varrendo um índice disponível que corresponda à especificação, ou varrendo a tabela em ordem física e fazendo uma classificação explícita. Para uma consulta que requer a varredura de uma grande fração da tabela, uma classificação explícita provavelmente será mais rápida que usar o índice, porque requer menos E/S de disco devido a seguir um padrão de acesso sequencial. Os índices são mais úteis quando apenas algumas linhas precisam ser encontradas. Um caso especial importante é ORDER BY combinado com LIMIT n: uma classificação explícita terá que processar todos os dados para identificar as primeiras n linhas, mas se houver um índice correspondente ao ORDER BY, as primeiras n linhas podem ser recuperadas diretamente, sem varrer as restantes.

Por padrão, os índices B-Tree armazenam suas entradas em ordem crescente, com valores nulos por último (o TID da tabela é tratado como uma coluna de desempate para entradas idênticas), significando que a varredura para frente de um índice na coluna x produz uma saída que satisfaz ORDER BY x (ou mais detalhadamente, ORDER BY x ASC NULLS LAST). O índice também pode ser varrido para trás, produzindo uma saída que satisfaça ORDER BY x DESC (ou mais detalhadamente, ORDER BY x DESC NULLS FIRST, uma vez que NULLS FIRST é o padrão para ORDER BY DESC).

A ordem de um índice B-Tree pode ser ajustada incluindo as opções ASC, DESC, NULLS FIRST e/ou NULLS LAST ao criar o índice; por exemplo:

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

Um índice armazenado em ordem crescente com nulos primeiro pode satisfazer tanto ORDER BY x ASC NULLS FIRST, quanto ORDER BY x DESC NULLS LAST, dependendo da direção em que é varrido.

Você pode se perguntar por que se preocupar em fornecer todas as quatro opções, quando duas opções, junto com a possibilidade de varredura para trás, cobririam todas as variantes de ORDER BY. Em índices de uma única coluna, as opções são, na verdade, redundantes, mas em índices multicoluna podem ser úteis. Considere um índice de duas colunas em (x, y): este índice pode satisfazer ORDER BY x, y se for varrido para frente, ou ORDER BY x DESC, y DESC se for varrido para trás. Mas pode ser que a aplicação precise usar frequentemente ORDER BY x ASC, y DESC. Não há como obter esta ordenação de um índice simples, mas será possível se o índice for definido como (x ASC, y DESC), ou (x DESC, y ASC).

Obviamente, índices com ordenações de classificação não-padrão são um recurso bastante especializado, mas às vezes podem produzir enormes acelerações para determinadas consultas. Se vale a pena manter este índice depende da frequência com que se usa consultas que exigem uma ordem de classificação especial.