“`html
Índices de Banco de Dados: como funcionam
Índices não são “atalhos mágicos”: eles alteram o caminho de execução do banco, trocando custo de escrita e espaço por
ganhos na leitura. Neste post eu explico, de forma técnica e prática, como os índices funcionam por baixo dos panos e
como isso impacta desempenho.
1 O que é um índice (e o que ele realmente guarda)
Um índice é uma estrutura auxiliar mantida pelo banco para acelerar operações como busca,
filtro e ordenação. Em vez de varrer uma tabela inteira,
o otimizador pode usar o índice para localizar rapidamente um conjunto menor de registros.
Na prática, o índice mapeia um valor de chave (uma ou mais colunas) para um local
da linha. Dependendo do banco, esse “local” pode ser:
- RID/TID (identificador físico da linha), ou
- ponteiro lógico para localizar a linha (por exemplo, via heap / clustered index).
onde estão as linhas, e só então acessa a tabela para retornar os dados.
2 Como o banco usa o índice: plano de execução e seletividade
Mesmo que um índice exista, o banco só vai usá-lo se fizer sentido. O otimizador escolhe um plano (estratégia) avaliando
estatísticas como:
- cardinalidade (quantidade de valores distintos)
- distribuição dos valores (parte deles pode ser muito comum)
- seletividade do filtro (fração estimada de linhas retornadas)
- custo de leituras adicionais e possíveis etapas extras
Em termos simplificados:
se o filtro retorna uma fração pequena da tabela, um índice tende a ajudar.
se retorna quase tudo, uma varredura sequencial pode ser mais barata.
Observação prática: você sempre quer validar com o EXPLAIN/EXPLAIN ANALYZE. Índice não é garantia,
é uma opção de caminho.
3 Estruturas comuns: B-Tree e o “caminho por páginas”
O índice mais comum em bancos relacionais é baseado em B-Tree. Ele organiza chaves em uma estrutura
hierárquica com páginas (blocos) para minimizar leituras de disco/IO.
O fluxo típico para uma consulta de igualdade ou faixa é:
- o banco entra na raiz da árvore;
- compara a chave e desce para o nó/página correta;
- repete até chegar ao nível das folhas;
- nas folhas, encontra as entradas com a chave e descobre os locais das linhas;
- por fim, acessa a tabela (ou pelo menos as páginas necessárias) para retornar os campos.
da árvore. Cada descida evita varrer milhares/milhões de linhas.
Outro ponto: índices por colunas diferentes mudam a forma como as chaves são “ordenadas” dentro do índice,
afetando diretamente operações de igualdade, intervalo e ORDER BY.
4 Custos e armadilhas: manutenção, duplicidade, cobertura e ordem das colunas
Índice melhora leitura, mas cobra caro na escrita e no consumo de recursos. Os custos principais são:
- Espaço em disco: o índice pode ser grande (principalmente em colunas largas).
- Escrita mais lenta: INSERT/UPDATE/DELETE precisam atualizar o índice.
- Fragmentação e concorrência: índices recebem muitas mudanças e podem exigir ajustes/rebalanceamentos.
Armadilha comum: índice para “toda” coluna
Colocar índices indiscriminadamente raramente melhora o sistema como um todo.
O que você quer é reduzir leituras com base no padrão real de consultas (filtros, junções e ordenação).
Ordem das colunas em índices compostos
Em índices compostos, a ordem importa porque a estrutura é ordenada pela primeira coluna, depois pela segunda, e assim por
diante. Isso afeta diretamente quais filtros conseguem aproveitar o índice.
(evitando ir à tabela) se as colunas necessárias estiverem presentes no índice. Isso pode reduzir “lookups” na tabela.
5 Exemplo prático: criar índice, conferir plano e entender o ganho
Um jeito confiável de validar índice é: criar (ou ajustar) o índice alinhado ao filtro/junção e comparar o plano antes e depois.
Abaixo vai um exemplo genérico em SQL (a sintaxe pode variar entre bancos).
-- Tabela exemplo:
-- orders(id, customer_id, status, created_at, total)
-- Consulta frequente: filtra por customer_id e status, ordena por created_at
SELECT id, created_at, total
FROM orders
WHERE customer_id = 123
AND status = 'PAID'
ORDER BY created_at DESC
LIMIT 50;
-- 1) Índice alinhado ao padrão do WHERE + ORDER BY
-- (ordem das colunas importa)
CREATE INDEX idx_orders_customer_status_created_at
ON orders (customer_id, status, created_at DESC);
-- 2) Ver o plano de execução (varia conforme o SGBD)
-- Exemplo genérico:
EXPLAIN (ANALYZE, BUFFERS)
SELECT id, created_at, total
FROM orders
WHERE customer_id = 123
AND status = 'PAID'
ORDER BY created_at DESC
LIMIT 50;
-- 3) Comparar:
-- - se antes fazia full scan (ou muito trabalho na tabela)
-- - depois passa a fazer index scan/seek
-- - e tende a reduzir leituras e tempo
Interpretação esperada: você quer que o plano use o índice para localizar as linhas do conjunto reduzido e, idealmente,
evite leituras desnecessárias (ou “lookups” excessivos).
Quer aprofundar e aplicar no seu projeto?
Leia outros posts aqui no yurideveloper.com e deixe seu banco mais rápido com decisões embasadas (índices, planos e modelagem).
“`
Sou Apaixonado pela programação e estou trilhando o caminho de ter cada diz mais conhecimento e trazer toda minha experiência vinda do Design para a programação resultando em layouts incríveis e idéias inovadoras! Conecte-se Comigo!