---
term: 'Índice de Banco de Dados'
seoTitle: 'O que é um Índice de Banco de Dados? Como a Indexação Funciona'
headline: 'O que é um Índice de Banco de Dados?'
slug: indice-de-banco-de-dados
category: database
shortDefinition: '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.'
relatedTerms:
  - database-queries
  - n-plus-one-query-problem
  - database-schema
  - multi-tenant-database-architecture
contrastsWith:
  - database-queries
faq:
  - question: 'O que é um índice de banco de dados em termos simples?'
    answer: '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.'
  - question: 'Quanto mais rápida é uma query indexada?'
    answer: '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.'
  - question: 'Índices deixam a escrita mais lenta?'
    answer: '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.'
  - question: 'Quais colunas devem ser indexadas?'
    answer: '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.'
  - question: 'Em que ordem devem ficar as colunas de um índice composto?'
    answer: '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.'
  - question: 'Como encontro índices ausentes ou sem uso?'
    answer: '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.'
  - question: 'O que são índices únicos, parciais e covering?'
    answer: '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.'
  - question: 'A indexação funciona igual em bancos de documentos?'
    answer: '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.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'PostgreSQL index types documentation'
    url: 'https://www.postgresql.org/docs/current/indexes-types.html'
  - name: 'Database index (Wikipedia)'
    url: 'https://en.wikipedia.org/wiki/Database_index'
  - name: 'MongoDB indexes documentation'
    url: 'https://www.mongodb.com/resources/basics/databases/database-index'
  - name: 'PostgreSQL — Using EXPLAIN'
    url: 'https://www.postgresql.org/docs/current/using-explain.html'
cta:
  title: 'Queries rápidas, índices visíveis'
  text: 'O Back4app coloca a gestão de índices onde o schema mora: crie e revise índices por classe no dashboard, no mesmo armazenamento com MongoDB que as suas queries acessam — sem scripts de migração, sem adivinhar de quais campos os seus filtros precisam.'
  linkText: 'Comece grátis'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-08-20'
translationKey: database-index
---

**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

| Pergunta | Resposta |
| --- | --- |
| O que é | Uma estrutura lateral ordenada: valores + ponteiros, como o índice de um livro |
| O ganho | Busca logarítmica em vez de varredura linear — decisivo em escala |
| O imposto | Toda escrita atualiza todo índice; o armazenamento cresce |
| O que indexar | Colunas de filtro, de join/ponteiro e de ordenação — se forem seletivas |
| O diagnóstico | EXPLAIN: um table scan numa tabela grande é o sinal |

## O índice, criado e sentido

```sql
-- 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:**

```javascript
// 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.
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// The query shape tells you the index: (status, createdAt)
final query = QueryBuilder<ParseObject>(ParseObject('Order'))
  ..whereEqualTo('status', 'pending')      // equality first…
  ..whereGreaterThan('createdAt', since)   // …then the range
  ..orderByDescending('createdAt');        // …sorted by the same column
final response = await query.query();
// Indexed: milliseconds at any size. Unindexed: a full collection scan.
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// The query shape tells you the index: (status, createdAt)
let query = Order.query("status" == "pending", "createdAt" > since)
  .order([.descending("createdAt")])
query.find { result in
  if case .success(let backlog) = result { render(backlog) }
}
// Indexed: milliseconds at any size. Unindexed: a full collection scan.
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// The query shape tells you the index: (status, createdAt)
val query = ParseQuery.getQuery<ParseObject>("Order")
query.whereEqualTo("status", "pending")     // equality first…
query.whereGreaterThan("createdAt", since)  // …then the range
query.orderByDescending("createdAt")        // …sorted by the same column
query.findInBackground { backlog, e -> if (e == null) render(backlog) }
// Indexed: milliseconds at any size. Unindexed: a full collection scan.
```

## Como o salto funciona

```mermaid
flowchart TB
  accTitle: Um lookup em índice B-tree
  accDescr: 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.
  R["Nó raiz<br/>(faixas)"] --> B1["Ramo<br/>A–M"]
  R --> B2["Ramo<br/>N–Z"]
  B2 --> L1["Folha: 'pending' → linhas 88, 1042, 55913"]
  B1 --> L2["Folha …"]
  L1 --> T["Busca exatamente essas linhas"]
```

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?

| Tipo | Atende | Use quando |
| --- | --- | --- |
| B-tree (padrão) | `=`, `<`, `>`, ranges, ordenação, prefixos | Quase sempre — o generalista |
| Hash | Só igualdade, O(1) | Lookups de correspondência exata, nada mais |
| Composto | Multicoluna, prefixo à esquerda | A query quente filtra por várias colunas |
| Único | B-tree + sem duplicados | Constraint e índice em um só |
| Parcial | Uma fatia filtrada de linhas | Subconjuntos quentes: não enviados, não lidos, ativos |
| Covering | Query respondida só pelo índice | Queries de leitura pesada com lista estável de colunas |
| Full-text (invertido) | Palavras → documentos | Caixas de busca |
| Geoespacial | Pontos, regiões, distância | Queries 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](https://www.mongodb.com/resources/basics/databases/database-index), 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](https://www.postgresql.org/docs/current/using-explain.html) 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](/glossary/multi-tenant-database-architecture/) 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 coluna | Nenhuma query de produção a usa |
| O EXPLAIN mostra scans numa tabela que cresce | A 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 ponteiro | A tabela é dominada por escrita e a leitura é rara |
| Uma regra de unicidade precisa ser imposta de todo modo | Você 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.
