Índices aceleram leitura, mas “cobram pedágio” na escrita
Quando você cria um índice, você ganha velocidade em consultas de leitura (SELECT), porque o banco passa a ter uma estrutura extra para localizar linhas com menos trabalho. O custo é que essa estrutura precisa ser mantida sempre que os dados mudam. Em termos práticos: cada INSERT, UPDATE ou DELETE pode exigir alterações em um ou vários índices, além da própria tabela.
Uma forma útil de pensar: para cada índice adicional, você está adicionando mais “lugares” onde o banco precisa escrever. Em cargas com muita escrita, isso pode virar o gargalo.
O que exatamente é “manutenção de índice”
- Inserção: além de gravar a nova linha na tabela, o banco precisa inserir uma nova entrada em cada índice aplicável.
- Atualização: se a atualização mexer em colunas indexadas (ou em colunas que participam do índice), o banco pode precisar remover a entrada antiga e inserir uma nova (na prática, é como um “delete + insert” dentro do índice).
- Deleção: o banco precisa remover (ou marcar como removida) a entrada do índice e, em muitos mecanismos, lidar depois com limpeza/compactação.
Além disso, índices ocupam espaço e podem sofrer fragmentação (páginas com buracos, páginas meio vazias, mais saltos de leitura), o que pode exigir reorganização ou rebuild dependendo do banco.
Impacto em INSERT: páginas e “splits” (conceito)
Muitos índices (especialmente B-tree) armazenam dados em páginas (blocos). Quando você insere uma nova chave, o banco precisa colocá-la na página correta para manter a ordem. Se a página já estiver cheia, ocorre um page split (divisão de página): o banco cria uma nova página, move parte das entradas e ajusta ponteiros. Isso aumenta o custo do INSERT porque vira mais I/O e mais trabalho interno.
Quando INSERT tende a ser mais caro
- Muitos índices na tabela: cada INSERT atualiza todos eles.
- Chave do índice “espalha” inserções: se a chave inserida cai em posições aleatórias do índice, aumenta a chance de splits e fragmentação.
- Alta concorrência: mais escrita simultânea pode aumentar contenção (locks/latches) nas páginas do índice.
Passo a passo prático: como perceber que INSERT está pagando caro por índices
- Meça o tempo do INSERT (antes/depois) em um ambiente de teste com volume representativo.
- Conte quantos índices existem na tabela e identifique quais são realmente usados por consultas frequentes.
- Observe sinais de splits/fragmentação nas ferramentas do seu banco (visões de estatísticas/DMVs/relatórios). O nome exato muda, mas a ideia é procurar métricas de “fragmentation”, “page splits”, “leaf page density” ou equivalentes.
- Teste removendo/ajustando índices não essenciais (em staging) e compare throughput de escrita.
Impacto em UPDATE: quando atualizar vira “mover” no índice
Nem todo UPDATE custa igual. Se você atualiza uma coluna que não participa de nenhum índice, o banco normalmente altera só a linha (e talvez algum metadado interno). Mas se você atualiza uma coluna indexada, o índice precisa refletir o novo valor.
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
Dois cenários comuns
- UPDATE em coluna não indexada: custo principal é localizar a linha e gravar a mudança.
- UPDATE em coluna indexada: o banco precisa remover a entrada antiga do índice e inserir a nova na posição correta. Isso pode causar splits e fragmentação, parecido com INSERT.
Em índices compostos, atualizar qualquer coluna que faça parte da chave do índice pode exigir essa remoção/inserção. Além disso, se a atualização aumenta o tamanho da linha (por exemplo, um texto maior), alguns bancos podem precisar realocar a linha, o que também afeta estruturas que apontam para ela.
Exemplo prático (conceitual)
-- Imagine um índice em (status, created_at)Se você faz:
UPDATE pedidos SET status = 'enviado' WHERE id = 123;O banco pode precisar tirar a entrada antiga do índice (status='pago', created_at=...) e inserir uma nova (status='enviado', created_at=...). Em uma tabela com alto volume de atualizações de status, esse índice pode virar um custo constante.
Passo a passo prático: reduzindo custo de UPDATE relacionado a índices
- Liste as colunas mais atualizadas (por exemplo: status, flags, campos de “último acesso”).
- Verifique se essas colunas estão indexadas e se o índice é realmente necessário para consultas críticas.
- Evite indexar campos muito “mutáveis” quando o ganho de leitura não compensa o custo de escrita.
- Se a consulta precisa do índice, avalie alternativas: ajustar o índice para atender a consulta com menos colunas, ou mudar a estratégia de consulta para reduzir dependência desse campo.
Impacto em DELETE: marcação, limpeza e espaço
Em muitos bancos, um DELETE não significa “apagar imediatamente tudo do disco”. Frequentemente ocorre:
- Marcação lógica: a linha é marcada como removida.
- Remoção/atualização de entradas nos índices: a estrutura do índice precisa deixar de apontar para aquela linha.
- Limpeza posterior: processos internos (ou manutenção) podem consolidar espaço, remover versões antigas e reduzir fragmentação.
O efeito prático: DELETE pode ser caro em tabelas com muitos índices, e também pode deixar “buracos” (espaço não reaproveitado imediatamente), aumentando fragmentação e impactando leituras futuras.
Passo a passo prático: lidando com deleções frequentes
- Meça a taxa de DELETE e identifique tabelas com deleção intensa.
- Verifique quantos índices existem nessas tabelas (cada um precisa ser atualizado).
- Monitore fragmentação e crescimento: deleções podem manter o arquivo grande mesmo com menos linhas ativas.
- Planeje manutenção (reorganização/rebuild/compactação) conforme as ferramentas do seu banco e janelas de operação.
Quantos índices são “demais”?
Não existe um número mágico, porque depende do padrão de acesso. Mas existe um princípio prático: cada índice deve pagar o próprio custo. Se um índice não é usado (ou é raramente usado), ele só adiciona:
- Mais tempo de escrita (INSERT/UPDATE/DELETE mais lentos).
- Mais armazenamento (o índice é uma cópia parcial/ordenada de dados + ponteiros).
- Mais manutenção (estatísticas, reorganização, rebuild, cache/buffer).
Sinais de excesso de índices
- Escritas lentas mesmo com consultas simples de INSERT/UPDATE.
- Muitos índices parecidos (mesmas colunas em ordens diferentes, ou índices redundantes).
- Índices “de tentativa” criados para casos pontuais e nunca revisados.
- Crescimento de armazenamento desproporcional ao crescimento de dados.
Checklist prático para “enxugar” índices com segurança
- Inventarie os índices por tabela (nome, colunas, tipo, tamanho).
- Verifique uso real (estatísticas de uso do banco, logs de consultas, APM). Procure índices com baixa ou nenhuma leitura.
- Identifique redundância: um índice pode cobrir outro (por exemplo, um índice mais “largo” pode tornar um mais “estreito” desnecessário, dependendo do banco e das consultas).
- Teste a remoção em staging e rode o conjunto de consultas críticas + carga de escrita. Compare latência e throughput.
- Remova por etapas (um índice por vez) para isolar impacto.
Balanceando leitura vs escrita por perfil de carga (conceitual)
Cargas tipo OLTP (muitas transações curtas, muita escrita)
- Priorize poucos índices, bem escolhidos, focados nas consultas mais críticas (as que realmente precisam ser rápidas).
- Evite indexar campos muito atualizados (status, flags voláteis) se não forem essenciais.
- Revise índices regularmente: em OLTP, um índice “a mais” pode derrubar throughput.
- Planeje manutenção para reduzir fragmentação quando necessário, mas com cuidado para não competir com a carga.
Cargas analíticas (mais leitura pesada, menos escrita)
- Aceite mais índices se eles reduzirem muito o custo das consultas (filtros, ordenações, junções), porque a escrita é menos frequente.
- Escritas em lote (quando existem) podem sofrer com muitos índices; considere janelas de carga e manutenção.
- Armazenamento e manutenção ainda importam: índices demais podem aumentar custo operacional e tempo de carga.
Regra prática de decisão
| Se o seu sistema... | Tendência | Estratégia |
|---|---|---|
| Escreve o tempo todo (muitos INSERT/UPDATE/DELETE) | Menos índices | Manter só os que sustentam consultas essenciais e integridade/constraints necessárias |
| Lê muito mais do que escreve | Mais índices | Adicionar índices que reduzam custo de consultas recorrentes, monitorando espaço e manutenção |
| Tem picos de escrita e picos de leitura | Equilíbrio | Índices para o “caminho crítico” + revisão periódica + manutenção planejada |