CodeGym /Cursos /SQL SELF /Problemas de indexação excessiva

Problemas de indexação excessiva

SQL SELF
Nível 38, Lição 2
Disponível

Índices são, sem dúvida, um jeito massa de turbinar seu banco de dados, mas como dizem por aí, “o ótimo é inimigo do bom”. Nem todo índice é útil, e quando tem índice demais, pode mais atrapalhar do que ajudar. Parece estranho, mas é isso mesmo. Bora entender melhor.

Imagina uma biblioteca gigante, onde pra achar os livros tem vários catálogos — tipo por autor, por gênero, por ano de publicação. Cada catálogo desses ajuda a encontrar o livro rapidinho. Mas se tiver catálogo demais — tipo pra cada palavra do título ou cada detalhe — ao invés de ajudar, vira bagunça: demora mais pra achar, ocupa espaço pra caramba, e o bibliotecário tem que ficar atualizando tudo o tempo todo.

No banco de dados, os índices funcionam mais ou menos assim: eles ajudam a achar os dados rápido, mas se tiver índice demais, atualizar tudo quando adiciona ou muda um registro vira um perrengue. E o espaço em disco também sofre. Fora que, com índice demais, o sistema pode até se confundir sobre qual usar.

Então, igual aos catálogos da biblioteca, com índices é melhor não exagerar — é melhor ter poucos e bons do que um monte inútil.

Bora brincar de "detetive do PostgreSQL". Imagina que você criou três índices pra uma coluna só. Fez isso achando que ia melhorar a performance. Mas olha só:

  • Se sua tabela é uma lista grandona de estudantes e tem três índices, cada vez que você adiciona um estudante, vai rolar três atualizações de índice. Não parece que ficou mais rápido, né?
  • E se você tem 10 tabelas dessas, cada uma cheia de índice? A performance do banco inteiro vai pro saco.

Como saber se você tá com indexação demais?

A primeira coisa pra descobrir se tem problema é olhar os índices que já existem. No PostgreSQL, dá pra ver isso com o comando:

\d nome_da_tabela

Esse comando mostra a tabela, as colunas e os índices ligados nela. Se você ver um monte de índice numa tabela só, já é motivo pra desconfiar.

Outro truque massa é usar a view do sistema pg_stat_user_indexes. Ela mostra o quanto os índices são usados, então dá pra sacar se tem índice “peso morto”:

SELECT
    relname AS table_name,
    indexrelname AS index_name,
    idx_scan AS index_scans
FROM
    pg_stat_user_indexes
WHERE
    idx_scan = 0;

Se idx_scan for 0, quer dizer que o índice nunca foi usado nas queries. Esse aí é candidato forte pra ser deletado.

Exemplo de indexação excessiva

Imagina uma tabela de usuários:

CREATE TABLE users (
    user_id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE,
    username VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW()
);

E a gente tem três índices:

-- Índice em email
CREATE INDEX idx_users_email ON users (email);

-- Índice em username
CREATE INDEX idx_users_username ON users (username);

-- Índice em created_at
CREATE INDEX idx_users_created_at ON users (created_at);

Agora bora ver os tipos de query que a gente faz normalmente:

  1. Buscar usuário pelo email.
  2. Buscar usuário pelo username.
  3. Ordenar usuários por created_at.

Parece que os índices são úteis. Mas olha o detalhe: se essas queries são raras (tipo, uma vez por semana), criar índice não vale a pena. E se alguns desses índices nunca são usados, eles só vão pesar nas operações de insert e update.

Pra ilustrar: imagina que temos esses dados na tabela users:

user_id email username created_at
1 alex.lin@mail.com alexlin 2024-06-15 10:23:00
2 anna.min@mail.com annamin 2024-06-16 12:47:00
3 otto.song@mail.com ottosong 2024-06-17 08:30:00
4 maria.chi@mail.com mariachi 2024-06-18 14:10:00

Se quase nunca rola busca por username, o índice idx_users_username nunca é usado (idx_scan = 0) e pode ser removido pra otimizar.

Ou seja, índice é uma ferramenta top, mas tem que usar com cabeça. Melhor ter poucos e bem usados do que um monte sobrando.

Como evitar indexação demais

  1. Analise os índices usados. Como já falamos, dá uma olhada na estatística de uso dos índices com pg_stat_user_indexes. Se o índice quase não é usado, provavelmente pode ser removido:
DROP INDEX IF EXISTS nome_do_índice;
  1. Crie índices só pros queries que você usa muito. Antes de criar um índice, se pergunte:
  • Essa coluna aparece muito em WHERE, ORDER BY, GROUP BY?
  • A tabela tem muitos dados?
  • A query realmente fica lenta sem índice?

Se a resposta for "não" pra qualquer uma dessas, talvez nem precise criar o índice.

  1. Use índices compostos. Se você sempre usa várias colunas juntas numa query, ao invés de criar um índice pra cada, faz um composto:
CREATE INDEX idx_users_email_username ON users (email, username);

Isso acelera queries que filtram por email e username ao mesmo tempo.

  1. Revise seus índices de tempos em tempos. Com o crescimento do banco, suas queries podem mudar. O que era útil ano passado pode ser inútil hoje. Então, revisa seus índices de vez em quando e apaga os que não servem mais.

Minimizando índices na prática

Bora voltar pra nossa tabela users. Ao invés de três índices separados, dá pra otimizar assim:

  • Tira o índice de created_at se quase nunca rola ordenação por ele.
  • Ao invés de dois índices separados pra email e username, faz um composto:
CREATE INDEX idx_users_email_username ON users (email, username);

Resumo: qual é o segredo do equilíbrio?

Como em muita coisa de programação, aqui vale o minimalismo: "Menos é mais". Não precisa indexar toda coluna só porque dá. Pensa bem pra que serve o índice e se ele realmente vai melhorar a performance. Seja pragmático e lembra: dev bom não é quem sai criando índice pra tudo, mas quem entende o impacto e usa do jeito certo.

Agora, com essa ferramenta na mão, você já pode evitar o desastre da indexação excessiva e deixar seu banco de dados voando igual guepardo, e não arrastando igual tartaruga carregando índice inútil.

2
Tarefa
SQL SELF, nível 38, lição 2
Bloqueado
Identificação de índices não utilizados
Identificação de índices não utilizados
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION