O que é um Índice de Banco de Dados?

Atualizado em: agosto de 2026

Um índice de banco de dados é uma estrutura de busca ordenada que permite à engine encontrar as linhas certas diretamente, em vez de varrer a tabela inteira. A analogia do livro é exata: ninguém encontra “idempotência” num livro de 900 páginas lendo o livro — a pessoa consulta o índice e pula para a página. Bancos de dados fazem a mesma escolha em cada query, e poder pular ou não é a diferença mais comum entre uma query de 5 milissegundos e uma de 5 segundos.

Principais pontos

PerguntaResposta
O que éUma estrutura lateral ordenada: valores + ponteiros, como o índice de um livro
O ganhoBusca logarítmica em vez de varredura linear — decisivo em escala
O impostoToda escrita atualiza todo índice; o armazenamento cresce
O que indexarColunas de filtro, de join/ponteiro e de ordenação — se forem seletivas
O diagnósticoEXPLAIN: um table scan numa tabela grande é o sinal

O índice, criado e sentido

-- O cavalo de batalha: um índice composto com o formato da query quente
CREATE INDEX orders_pending ON orders (status, created_at);

-- Especializações da mesma ideia:
CREATE UNIQUE INDEX users_email ON users (email);         -- constraint + velocidade
CREATE INDEX unshipped ON orders (created_at)
  WHERE shipped = false;                                  -- parcial: só o subconjunto quente

-- O antes/depois, pelo plano:
EXPLAIN SELECT * FROM orders WHERE status = 'pending' AND created_at > now() - interval '1 day';
--  antes:   Seq Scan on orders   (linhas examinadas: 4.812.309)
--  depois:  Index Scan using orders_pending   (linhas examinadas: 1.214)

O código de aplicação encontra a mesma física pela forma da query — esta query é a especificação do índice (status, createdAt), seja qual for a superfície que a escreve:

// JavaScript / Node.js — Back4app JS SDK
// The query shape tells you the index: (status, createdAt)
const query = new Parse.Query('Order');
query.equalTo('status', 'pending');       // equality first…
query.greaterThan('createdAt', since);    // …then the range
query.descending('createdAt');            // …sorted by the same column
const backlog = await query.find();
// Indexed: milliseconds at any size. Unindexed: a full collection scan.

Como o salto funciona

Um lookup em índice B-treeUma query desce uma árvore ordenada e rasa, da raiz, passando por um nó intermediário, até uma folha que guarda o valor buscado e os ponteiros de linha, tocando um punhado de páginas em vez de varrer a tabela inteira.

Nó raiz
(faixas)

Ramo
A–M

Ramo
N–Z

Folha: 'pending' → linhas 88, 1042, 55913

Folha …

Busca exatamente essas linhas

Uma query desce uma árvore ordenada e rasa, da raiz, passando por um nó intermediário, até uma folha que guarda o valor buscado e os ponteiros de linha, tocando um punhado de páginas em vez de varrer a tabela inteira.

A estrutura padrão em toda parte é a B-tree: rasa, ordenada, autobalanceada — três ou quatro níveis cobrem centenas de milhões de entradas, e as suas folhas são encadeadas, razão pela qual uma mesma estrutura atende igualdade, ranges e ORDER BY. Essa versatilidade é o motivo de “na dúvida, B-tree” ser o conselho permanente, com as alternativas atuando como especialistas.

B-tree vs. hash vs. os especialistas

Qual tipo de índice você deveria usar?

TipoAtendeUse quando
B-tree (padrão)=, <, >, ranges, ordenação, prefixosQuase sempre — o generalista
HashSó igualdade, O(1)Lookups de correspondência exata, nada mais
CompostoMulticoluna, prefixo à esquerdaA query quente filtra por várias colunas
ÚnicoB-tree + sem duplicadosConstraint e índice em um só
ParcialUma fatia filtrada de linhasSubconjuntos quentes: não enviados, não lidos, ativos
CoveringQuery respondida só pelo índiceQueries de leitura pesada com lista estável de colunas
Full-text (invertido)Palavras → documentosCaixas de busca
GeoespacialPontos, regiões, distânciaQueries de “perto de mim”

Duas regras carregam a linha do composto: a regra do prefixo à esquerda — um índice em (a, b, c) atende a, (a, b), (a, b, c), nunca b sozinho — e igualdade primeiro, range/ordenação por último na ordem das colunas (o mnemônico ESR na indexação de bancos de documentos, onde as mesmas B-trees fazem o mesmo trabalho).

Quando indexar — e quando não

Indexe: colunas em filtros WHERE frequentes; chaves de join e campos de ponteiro (algumas engines nunca indexam foreign keys automaticamente — um clássico table scan silencioso); colunas de ORDER BY em caminhos quentes; e sempre com a seletividade em mente — uma coluna de e-mail (milhões de valores distintos) se paga, um flag de status (três valores) em geral não se paga sozinho, embora brilhe liderando um composto com um range atrás. Não indexe: tabelas pequenas que a engine varre mais rápido do que busca; tabelas quentes de escrita além dos poucos índices essenciais; colunas já atendidas pelo prefixo esquerdo de um índice existente; e qualquer coisa para a qual você não consegue nomear uma query — índice sem query é puro imposto de escrita. O ciclo de auditoria: rode EXPLAIN nas queries lentas procurando scans, confira as estatísticas de uso para achar índices mortos, adicione e remova de acordo.

Casos de uso comuns

  • A query da lista quente. Filtros de status + data atrás de todo dashboard e feed — o território natural do índice composto.
  • Campos de login e lookup. E-mail, username, IDs externos — índices únicos fazendo constraint e velocidade ao mesmo tempo.
  • Caminhos de join e ponteiro. Toda foreign key e todo ponteiro que as suas queries percorrem; o cúmplice silencioso do problema N+1 é um deles sem índice.
  • Filtros multi-tenant. Compostos liderados pelo tenant — a regra da arquitetura multi-tenant de que todo índice começa com tenant_id.
  • Busca e geo. Índices invertidos e espaciais movendo as queries que B-trees não atendem.

Você deveria adicionar esse índice? Matriz de decisão

Adicione quando…Pule quando…
Uma query frequente filtra ou ordena por essa colunaNenhuma query de produção a usa
O EXPLAIN mostra scans numa tabela que cresceA tabela é pequena e vai continuar pequena
A coluna é seletiva (muitos valores distintos)O prefixo de um índice existente já a cobre
É chave de join ou campo de ponteiroA tabela é dominada por escrita e a leitura é rara
Uma regra de unicidade precisa ser imposta de todo modoVocê está chutando — meça primeiro

A disciplina em uma frase: índices são criados em resposta a queries, revisados contra o uso real e removidos sem sentimentalismo.

Limitações e trade-offs

  • A escrita paga pela leitura. Cada índice é mais uma estrutura que toda escrita precisa manter — cargas em lote notoriamente rodam mais rápido com os índices derrubados e reconstruídos depois.
  • O armazenamento é real. Índices comumente rivalizam com o tamanho da própria tabela; covering indexes, em especial, trocam disco por velocidade.
  • Quem decide é o otimizador, não você. Um índice de baixa seletividade pode ser ignorado com razão; estatísticas desatualizadas podem ignorar sem razão um índice bom — o plano é a verdade.
  • Erros de ordem neutralizam compostos. (created_at, status) e (status, created_at) são ferramentas diferentes; a regra do prefixo à esquerda não perdoa nada.
  • Índice não conserta a query. Wildcards no início, funções sobre colunas e loops N+1 derrotam a indexação por cima — a forma da query vem primeiro.

Índices no Back4app

O Back4app é uma plataforma open-source de Backend as a Service (BaaS) que combina banco de dados gerenciado, APIs REST e GraphQL geradas automaticamente, autenticação, armazenamento de arquivos e funções serverless com Cloud Code. A gestão de índices mora junto com o schema no dashboard: crie, revise e remova índices por classe — de campo único ou compostos — no armazenamento com MongoDB que as suas queries de SDK realmente acessam, seguindo a mesma lógica de B-tree e ESR acima. A query das abas de código e o índice que a atende são desenhados no mesmo lugar — exatamente onde a disciplina de “indexe o que você consulta” quer morar.

Perguntas frequentes

O que é um índice de banco de dados em termos simples?

Uma estrutura separada e ordenada — geralmente uma B-tree — que guarda valores de coluna mais ponteiros para as suas linhas, exatamente como o índice de um livro guarda termos e números de página. A engine procura o valor na pequena estrutura ordenada e pula direto para as linhas correspondentes, em vez de ler a tabela inteira na esperança de encontrá-las.

Quanto mais rápida é uma query indexada?

A diferença entre trabalho logarítmico e linear: um lookup em B-tree toca um punhado de páginas, tenha a tabela dez mil linhas ou cem milhões, enquanto um table scan lê tudo. Em tamanhos pequenos os dois parecem instantâneos — e é por isso que índices ausentes se escondem em desenvolvimento e detonam em produção, onde a mesma query passa a examinar milhões de linhas.

Índices deixam a escrita mais lenta?

Sim — esse é o imposto. Todo insert, update ou delete numa coluna indexada precisa atualizar também cada índice que a referencia: seis índices numa tabela significam até seis atualizações extras de estrutura por escrita, mais o armazenamento que eles ocupam. Índices são uma compra de velocidade de leitura paga em velocidade de escrita e disco — os deliberados se pagam, os esquecidos só te cobram.

Quais colunas devem ser indexadas?

As colunas que as suas queries realmente usam: filtros (WHERE), chaves de join — incluindo foreign keys e campos de ponteiro, que algumas engines não indexam automaticamente — e colunas de ordenação (ORDER BY). Some o teste de seletividade: uma coluna de e-mail que distingue milhões de linhas merece o índice; um flag booleano que divide a tabela ao meio, em geral, não.

Em que ordem devem ficar as colunas de um índice composto?

Igualdade primeiro, range e ordenação depois — e lembre da regra do prefixo à esquerda: um índice em (a, b, c) atende queries que filtram por a, por a e b, ou pelas três, mas nunca por b sozinho. A formulação da mesma regra nos bancos de documentos é ESR: Equality, Sort, Range. A ordem das colunas é a diferença entre um índice composto funcionar e apenas existir.

Como encontro índices ausentes ou sem uso?

Para os ausentes: rode o plano da query — EXPLAIN — e procure table scans em tabelas grandes; a coluna de filtro de uma query lenta e frequente é a candidata. Para os sem uso: toda engine rastreia estatísticas de uso de índices, e um índice que nenhuma query toca há meses é puro imposto de escrita — remova. O plano e as estatísticas, juntos, são a metodologia inteira.

O que são índices únicos, parciais e covering?

Especializações da mesma estrutura: um índice único impõe a regra de não haver duplicados como constraint enquanto acelera lookups; um índice parcial cobre apenas as linhas que atendem a uma condição — pequeno e rápido para subconjuntos quentes, como pedidos não enviados; um covering index contém todas as colunas de que a query precisa, permitindo que a engine responda só com o índice, sem visitar a tabela.

A indexação funciona igual em bancos de documentos?

Conceitualmente idêntica — B-trees sobre valores de campos — com os mesmos trade-offs e a mesma lógica de prefixo à esquerda sob a regra prática ESR. Bancos de documentos adicionam índices multikey sobre campos de array e variantes geoespaciais, e a regra operacional sobrevive à tradução: indexe o que você consulta, especialmente os campos de ponteiro que joins e includes percorrem.

Termos relacionados

Compare com

Leitura adicional

Pronto para construir seu backend?

Comece seu projeto no Back4app em minutos — banco de dados, autenticação, APIs e Cloud Code incluídos. Sem cartão de crédito.

Escrito e revisado por Back4app Engineering, Back4app Engineering · Publicado em 2026-08-20