11.3. Índices multicoluna #

Um índice pode ser definido sobre mais de uma coluna da tabela. Por exemplo, havendo uma tabela com esta forma:

CREATE TABLE test2 (
  major int,
  minor int,
  name varchar
);

(digamos que seja mantido o diretório /dev em um banco de dados...), e são frequentemente feitas consultas como:

SELECT name FROM test2 WHERE major = constante AND minor = constante;

então pode ser apropriado definir um índice com as colunas major e minor juntas. Por exemplo:

CREATE INDEX test2_mm_idx ON test2 (major, minor);

No momento, apenas os tipos de índice B-Tree, GiST, GIN e BRIN dão suporte a índices multicoluna. A possibilidade de haver múltiplas colunas-chave é independente das colunas INCLUDE poderem ser adicionadas ao índice. Os índices podem ter até 32 colunas, incluindo as colunas INCLUDE. (Este limite pode ser alterado ao construir o PostgreSQL; veja o arquivo pg_config_manual.h.)

Um índice B-Tree multicoluna pode ser usado com condições na consulta que envolvem qualquer subconjunto das colunas do índice, mas o índice é mais eficiente quando há restrições nas primeiras colunas (as mais à esquerda). A regra exata é a seguinte: as restrições de igualdade nas primeiras colunas, mais quaisquer restrições de desigualdade na primeira coluna que não possua uma restrição de igualdade, serão sempre usadas para limitar a parte do índice que será varrida. As restrições nas colunas à direita destas colunas são verificadas no índice, portanto, elas sempre economizarão visitas à tabela propriamente dita, mas não necessariamente reduzem a porção do índice que precisa ser varrida. Se uma varredura de índice B-Tree puder aplicar a otimização de varredura de salto (skip scan) de forma eficaz, ela aplicará todas as restrições de coluna ao navegar pelo índice por meio de buscas repetidas. Isto pode reduzir a porção do índice que precisa ser lida, mesmo que uma ou mais colunas (anteriores à coluna menos significativa do índice, de acordo com o predicado da consulta) não possuam uma restrição de igualdade convencional. A varredura de salto funciona gerando internamente uma restrição de igualdade dinâmica que corresponde a todos os valores possíveis em uma coluna de índice (embora apenas para uma coluna que não possua uma restrição de igualdade proveniente do predicado da consulta, e somente quando a restrição gerada puder ser usada em conjunto com uma restrição de coluna posterior do predicado da consulta).

Por exemplo, dado um índice em (x, y), e uma condição de consulta WHERE y = 7700, uma varredura de índice B-Tree pode ser capaz de aplicar a otimização de varredura de salto. Isto geralmente acontece quando o planejador de consultas espera que buscas repetidas em WHERE x = N AND y = 7700 para cada valor possível de N (ou para cada valor de x que esteja armazenado no índice) seja a abordagem mais rápida possível, considerando os índices disponíveis na tabela. Esta abordagem geralmente só é adotada quando há tão poucos valores distintos de x que o planejador espera que a varredura ignore a maior parte do índice (porque a maioria de suas páginas folha não pode conter tuplas relevantes). Havendo muitos valores distintos de x terá que ser varrido todo o índice, portanto, na maioria dos casos, o planejador irá preferir uma varredura sequencial da tabela em vez de usar o índice.

A otimização de varredura de salto também pode ser aplicada seletivamente durante varreduras de B-Tree que tenham pelo menos algumas restrições úteis do predicado da consulta. Por exemplo, dado um índice em (a, b, c) e uma condição de consulta WHERE a = 5 AND b >= 42 AND c < 77, o índice pode ter que ser varrido desde a primeira entrada com a = 5 e b = 42 até a última entrada com a = 5. As entradas no índice com c >= 77 nunca precisarão ser filtradas no nível de tabela, mas pode ou não ser vantajoso ignorá-las no índice. Quando ocorre um salto, a varredura inicia uma nova procura no índice para se reposicionar a partir do final do agrupamento corrente a = 5 e b = N (ou seja, a partir da posição no índice onde a primeira tupla a = 5 AND b = N AND c >= 77 aparece.), para o início do próximo agrupamento deste tipo (ou seja, a posição no índice onde a primeira tupla a = 5 AND b = N + 1 aparece).

Um índice GiST multicoluna pode ser usado com condições na consulta que envolvem qualquer subconjunto das colunas do índice. As condições nas colunas adicionais restringem as entradas retornadas pelo índice, mas a condição na primeira coluna é a mais importante para determinar o quanto do índice precisa ser varrido. Um índice GiST será relativamente ineficaz se a sua primeira coluna tiver apenas alguns poucos valores distintos, mesmo havendo muitos valores distintos nas colunas adicionais.

Um índice GIN multicoluna pode ser usado com condições na consulta que envolvem qualquer subconjunto das colunas do índice. Ao contrário de B-Tree e GiST, a eficácia da procura de índice é a mesma, independentemente de quais colunas do índice são usadas pelas condições da consulta.

Um índice BRIN multicoluna pode ser usado com condições na consulta que envolvem qualquer subconjunto das colunas do índice. Assim como o GIN, e diferentemente da B-Tree e GiST, a eficácia da procura de índice é a mesma, independentemente de qual(is) coluna(s) do índice são usadas pelas condições da consulta. A única razão para haver vários índices BRIN em vez de um índice BRIN multicoluna em uma tabela, é ter uma configuração de armazenamento pages_per_range diferente.

Obviamente, cada coluna deve ser usada com operadores apropriados ao tipo de índice; cláusulas que envolvam outros operadores não são consideradas.

Os índices multicoluna devem ser usados com moderação. Na maioria das situações, um índice em uma única coluna é suficiente e economiza espaço e tempo. Índices com mais de três colunas provavelmente não serão úteis, a menos que o uso da tabela seja extremamente estilizado. Veja também na Seção 11.5 e na Seção 11.9 algumas discussões sobre os méritos de diferentes configurações de índice.