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 =constanteAND 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.