Índices Compostos (Multicoluna): Ordem das Colunas e Regra do Prefixo

Capítulo 5

Tempo estimado de leitura: 7 minutos

+ Exercício

O que é um índice composto (multicoluna)

Um índice composto é um único índice que armazena as chaves combinando duas ou mais colunas, por exemplo (A, B). Pense nele como uma lista ordenada primeiro por A e, dentro de cada valor de A, ordenada por B. Essa “ordenação em camadas” é o motivo pelo qual a ordem das colunas no índice muda completamente quais consultas conseguem aproveitar o índice com eficiência.

Exemplo mental rápido

Se você cria INDEX idx_ab (A, B), o banco consegue navegar rapidamente até um valor específico de A e, dentro desse “grupo”, localizar/varrer valores de B. Já se a consulta só fala de B (sem restringir A), o índice não está organizado para começar por B, então a navegação eficiente fica comprometida.

A regra do prefixo (leftmost prefix)

A “regra do prefixo” diz que um índice composto só é usado de forma eficiente quando as condições da consulta começam pela(s) primeira(s) coluna(s) do índice, na mesma ordem. Para um índice (A, B, C), os prefixos úteis são: (A), (A, B) e (A, B, C). Já (B), (C) ou (B, C) não são prefixos e, em geral, não permitem uma busca eficiente pelo índice.

O que significa “usar de forma eficiente”

  • Busca pontual (lookup): quando você fixa valores com igualdade (=) nas primeiras colunas do índice, o banco consegue ir direto ao trecho correto do índice.
  • Varredura ordenada (range scan): quando você fixa um prefixo e depois faz intervalo/ordenação na próxima coluna, o banco consegue percorrer uma faixa contígua do índice sem precisar ordenar depois.
  • Uso parcial: às vezes o índice é usado, mas com baixa eficiência (por exemplo, varrendo muitos registros) porque faltou restringir as primeiras colunas.

Como prever o uso do índice: um checklist prático

Para um índice (A, B), siga este passo a passo para prever se ele ajuda:

  1. Existe condição em A? Se não, a regra do prefixo falha (o índice tende a não ajudar para filtrar por B).
  2. Em A, é igualdade ou intervalo? Igualdade em A permite aproveitar B para filtrar/ordenar. Intervalo em A normalmente limita o quanto B pode ser aproveitado.
  3. Existe filtro em B? Se A está fixo por igualdade, B pode ser usado para buscar mais precisamente.
  4. Existe ORDER BY? Se o ORDER BY segue a ordem do índice e as colunas anteriores estão fixadas adequadamente, o banco pode evitar ordenação extra.

Cenários práticos com (A, B)

Vamos assumir uma tabela pedidos com colunas cliente_id (A) e data_pedido (B). Índice: (cliente_id, data_pedido).

Continue em nosso aplicativo e ...
  • Ouça o áudio com a tela desligada
  • Ganhe Certificado após a conclusão
  • + de 5000 cursos para você explorar!
ou continue lendo abaixo...
Download App

Baixar o aplicativo

CREATE INDEX idx_pedidos_cliente_data ON pedidos (cliente_id, data_pedido);

Cenário 1: WHERE A = ? AND B = ?

SELECT * FROM pedidos WHERE cliente_id = 42 AND data_pedido = '2026-01-10';
  • Previsão: o índice é usado com alta eficiência.
  • Por quê: a consulta usa o prefixo completo (A, B) com igualdade nas duas colunas. O banco encontra diretamente a chave composta correspondente (ou uma faixa mínima, dependendo de duplicidade).
  • Resultado típico: poucas leituras no índice e poucas leituras na tabela (ou nenhuma, se o índice cobrir as colunas selecionadas).

Cenário 2: WHERE A = ? ORDER BY B

SELECT * FROM pedidos WHERE cliente_id = 42 ORDER BY data_pedido;
  • Previsão: o índice é usado com alta eficiência para filtrar e para ordenar.
  • Por quê: A está fixo por igualdade, então dentro do “grupo” de cliente_id = 42 o índice já está ordenado por B. Assim, o banco pode retornar as linhas na ordem correta sem um passo extra de sort.
  • Observação: se você pedir ORDER BY data_pedido DESC, muitos bancos conseguem percorrer o índice ao contrário e ainda evitar sort.

Cenário 3: WHERE B = ? sem A

SELECT * FROM pedidos WHERE data_pedido = '2026-01-10';
  • Previsão: o índice (A, B) tende a não ser usado para filtrar por B de forma eficiente.
  • Por quê: falta a primeira coluna do índice (A). Como o índice está ordenado por A primeiro, os valores de B ficam “espalhados” ao longo de muitos grupos de A, impedindo uma busca direta por B.
  • O que fazer: se esse padrão for frequente e importante, considere um índice separado em (data_pedido) ou um índice composto com outra ordem, como (data_pedido, cliente_id), dependendo de outros filtros/ordenações.

Ordem das colunas e impacto em filtros e ordenações

Trocar (A, B) por (B, A) muda tudo

Compare as duas consultas abaixo e como elas se encaixam em cada índice:

ConsultaÍndice (A, B)Índice (B, A)
WHERE A = ? AND B = ?ÓtimoÓtimo
WHERE A = ?ÓtimoFraco/geralmente não ajuda
WHERE B = ?Fraco/geralmente não ajudaÓtimo
WHERE A = ? ORDER BY BÓtimo (evita sort)Geralmente não evita sort
WHERE B = ? ORDER BY AGeralmente não evita sortÓtimo (evita sort)

Mesmo quando ambos os índices podem ser usados em WHERE A=? AND B=?, a escolha da ordem é decisiva para consultas que usam apenas uma coluna, ou que dependem de ordenação.

Igualdade antes de intervalo (regra prática importante)

Em índices compostos, condições de igualdade nas primeiras colunas mantêm o índice “bem focado”. Já um intervalo (>, <, BETWEEN, LIKE 'prefix%') tende a abrir uma faixa maior. Depois que você entra em intervalo em uma coluna do índice, o aproveitamento das colunas seguintes para busca/ordenação costuma diminuir.

Exemplo com índice (cliente_id, data_pedido):

SELECT * FROM pedidos WHERE cliente_id = 42 AND data_pedido BETWEEN '2026-01-01' AND '2026-01-31' ORDER BY data_pedido;
  • Previsão: muito bom. Igualdade em cliente_id e intervalo em data_pedido; o índice permite varrer exatamente a faixa de datas daquele cliente já na ordem.

Agora invertendo a lógica (hipotético índice (data_pedido, cliente_id)):

SELECT * FROM pedidos WHERE data_pedido BETWEEN '2026-01-01' AND '2026-01-31' AND cliente_id = 42;
  • Previsão: pode filtrar pela faixa de datas, mas dentro dessa faixa o cliente_id pode não ser tão bem aproveitado quanto seria se ele viesse antes, porque o intervalo em data_pedido já expandiu a varredura.

Guia rápido: prever eficiência nos três cenários pedidos

1) WHERE A=? AND B=?

  • Índice (A, B): uso máximo (lookup altamente seletivo).
  • Índice (B, A): também pode ser máximo, mas escolha depende de outras consultas.

2) WHERE A=? ORDER BY B

  • Índice (A, B): excelente, filtra por A e já entrega ordenado por B.
  • Índice (B, A): não casa com a necessidade; pode exigir sort ou outro plano.

3) WHERE B=? sem A

  • Índice (A, B): regra do prefixo falha; tende a não ajudar (ou ajuda pouco).
  • Índice (B, A): excelente para filtrar por B.

Heurísticas para definir a ordem das colunas no índice composto

  • Priorize o padrão de consulta mais frequente: o melhor índice é o que acelera o que mais roda (e mais custa).
  • Seletividade primeiro (na maioria dos casos): coloque antes a coluna que mais reduz o conjunto de linhas quando filtrada por igualdade (ex.: cliente_id costuma ser mais seletivo que status).
  • Igualdade antes de intervalo: se uma consulta típica tem WHERE A = ? AND B BETWEEN ..., geralmente (A, B) é uma boa ordem.
  • Inclua colunas de ordenação logo após as colunas fixadas: para WHERE A=? ORDER BY B, prefira (A, B) para evitar sort.
  • Evite “pular” a primeira coluna: se muitas consultas filtram por B sem A, um índice (A, B) não atende bem; considere (B) ou (B, A) conforme o restante do workload.
  • Não tente um índice composto para tudo: às vezes dois índices menores (um para A e outro para B) atendem melhor padrões diferentes do que um único composto mal ordenado.

Agora responda o exercício sobre o conteúdo:

Em uma tabela com índice composto (cliente_id, data_pedido), qual consulta tende a aproveitar esse índice com mais eficiência para filtrar e também evitar uma ordenação extra?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

Com o índice (cliente_id, data_pedido), fixar cliente_id por igualdade permite usar o prefixo do índice; dentro desse grupo, os registros já ficam ordenados por data_pedido, evitando um sort extra.

Próximo capitúlo

Seletividade, Cardinalidade e Distribuição de Dados: Escolhendo Colunas para Indexar

Arrow Right Icon
Capa do Ebook gratuito Índices e Performance de Banco de Dados para Iniciantes: Como Acelerar Consultas sem Mistério
36%

Índices e Performance de Banco de Dados para Iniciantes: Como Acelerar Consultas sem Mistério

Novo curso

14 páginas

Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.