EXPLAIN bonito, índice inútil: a vida real no MySQL

Falaa Galera.
Dando continuidade no post anterior “Como Ler um Explain” quero compartilhar como decido se um índice será “bom” ou “ruim” no MySQL, obviamente que irei demonstrar boas práticas.

A ideia aqui não são teorias, e sim o que funciona no dia a dia quando você tem milhões de linhas 😅😅😅.

 

🎯 O problema clássico

Ao analisarmos diversas consultas dia a dia, acredito que vocês ja passaram por isto:

  • “Criei um índice e o MySQL não usou.”
  • “O índice tem cardinalidade baixa, então é ruim?”
  • “Esse índice é RUIM pela métrica, mas meu EXPLAIN melhorou muito… como assim?”

 

🧪 O ambiente de testes

Para quem ja utilizou do Sysbench alguma vez já esbarrou na famosa tabela SBTEST1. Uma tabela simples mas essencial para demonstração, pois contém dados que confundem o otimizador.

  • MySQL 8.x
  • InnoDB
  • Tabelas com centenas de milhões / bilhões de linhas
  • Dados com distribuição real (skew, repetições, hot keys)

Estrutura tabela.

Vemos que, existem apenas 2 indices (por padrão desta tabela) temos a chave PRIMARY (id) e KEY ‘k‘.
Coluna “c” e “pad” não são indexadas. Algo intencional criado pelo SysBench.

🧠 Dois conceitos que o MySQL usa (e muita gente mistura)

Cardinalidade

No MySQL, refere-se apenas aos valores exclusivos (distintos) presentes naquela coluna.
Sendo assim, utilizo este comando abaixo para ter uma noção estatística da distribuição da coluna.

Demostrando na prática.

  • Isto é o que o otimizador “MySQL” esta estimando.
  • Podemos estar desatualizados (necessitando um ANALYZE TABLE).

Agora, os 2 comandos que considero importantes para as validações de colunas é:

Na prática:

Retornando, em média quantas linhas cada valor estará retornando.
Essa métrica, verifica diretamente com o ROWS do EXPLAIN.

E também utilizo bastante esta regra abaixo, que com o tempo fui acompanhando.

Linhas por valor Avaliação prática
< 100 ⭐ índice excelente
100 – 5.000 ✅ índice bom
5.000 – 50.000 ⚠️ índice médio
> 50.000 ❌ índice ruim

🔎 Analisando os índices reais: Sbtest1

O primeiro,  coluna ID (o indice perfeito).

  • PRIMARY KEY
  • Lookup direto
  • 1 Linha.

✅ Nenhuma discussão aqui.

Coluna K, o índice que parece ruim, mas funciona.



Agora, o plano de execução:

✅ Reduziu milhões → centenas ✅ Índice usado corretamente
👉 Estatisticamente fraco, operacionalmente eficiente.
 

❌ O erro clássico: tentar indexar tudo.

Olhando para a coluna PAD, vemos uma alta variação de informações nela.
Sendo assim, o DBA pensa:

“Tem alta variabilidade, vou criar índice”.

Então:

vemos uma cardinalidade alta, algo como: 986400.
Até aqui, tudo parece ótimo.
 
Ainda mais quando vemos o EXPLAIN.
  • type: range
  • key: idx_pad
  • rows: 1
  • Using index condition

✅ Índice usado
✅ Poucas linhas
✅ Plano “bonito”

E é aqui onde muita gente para e conclui errado.

⚠️ Por que esse índice engana

O indice não é ruim tecnicamente –> Ele apenas funiciona.
O problema é o tipo de consulta que está sendo usada para justificá-lo.

Esse padrão:

  • ✅ usa prefixo
  • ✅ permite range scan no B‑Tree
  • ✅ favorece o índice

Ou seja: você escolheu a melhor query possível para o índice parecer bom.

🧠 Agora a pergunta que importa

“Essa é a query que realmente roda em produção?”

Porque basta trocarmos o operador para:

e o cenário muda completamente:

  • ❌ índice não pode ser usado
  • ❌ full scan inevitável
  • ❌ custo de escrita mantido
  • ❌ índice vira peso morto
O índice não está errado.
A justificativa para criá‑lo é que está errada.

No MySQL, cardinalidade refere‑se à quantidade estimada de valores distintos em uma coluna. Esse número é utilizado pelo otimizador como heurística, não como verdade absoluta.
E lembre‑se: sempre existirão casos onde a reescrita da query é a melhor opção, e eu super recomendo, desde que faça sentido no seu ambiente. O mais importante é garantir que essa reescrita aproveite índices existentes e bem desenhados, com boa capacidade de filtragem.
 
 
No próximo post, a ideia é focar exclusivamente nisso: como reescrever consultas de forma correta, aproveitando índices existentes, respeitando a ordem do B‑Tree e evitando padrões que forçam full scan desnecessário. Sem mágica, só prática.
 
 
 

Referências.

https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html
https://www.mysqltutorial.org/mysql-index/mysql-index-cardinality/
https://planetscale.com/learn/courses/mysql-for-developers/indexes/index-selectivity
https://dev.mysql.com/doc/refman/8.0/en/index-btree-hash.html

 

COMPARTILHE:
Picture of Henrique Borba Garcia

Henrique Borba Garcia

Iniciei meus estudos na área de Desenvolvimento no ano de 2021. Atualmente, em MySQL tenho uma experiência de 5 anos, e com bancos não relacionais (MongoDB) 2 anos. Desempenho o papel de LÍDER TÉCNICO para ambas as técnologias. Sou bastante persistente e proativo em diversos assuntos em banco de dados. Minhas certificações. . MySQL 2025 Solution Enginner Specialist Assessment. . MySQL Database Administrator 8.0 . MySQL Database Developer 8.0 . OCI Foundations 2021, 2022, 2023, e 2024. . MySQL Database Service . MySQL Explorer. . SQL Explorer. . Oracle Cloud Data Management 2023
Picture of Henrique Borba Garcia

Henrique Borba Garcia

Iniciei meus estudos na área de Desenvolvimento no ano de 2021. Atualmente, em MySQL tenho uma experiência de 5 anos, e com bancos não relacionais (MongoDB) 2 anos. Desempenho o papel de LÍDER TÉCNICO para ambas as técnologias. Sou bastante persistente e proativo em diversos assuntos em banco de dados. Minhas certificações. . MySQL 2025 Solution Enginner Specialist Assessment. . MySQL Database Administrator 8.0 . MySQL Database Developer 8.0 . OCI Foundations 2021, 2022, 2023, e 2024. . MySQL Database Service . MySQL Explorer. . SQL Explorer. . Oracle Cloud Data Management 2023

PARTICIPE

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

POSTADO POR
Picture of Henrique Borba Garcia

Henrique Borba Garcia

Iniciei meus estudos na área de Desenvolvimento no ano de 2021. Atualmente, em MySQL tenho uma experiência de 5 anos, e com bancos não relacionais (MongoDB) 2 anos. Desempenho o papel de LÍDER TÉCNICO para ambas as técnologias. Sou bastante persistente e proativo em diversos assuntos em banco de dados. Minhas certificações. . MySQL 2025 Solution Enginner Specialist Assessment. . MySQL Database Administrator 8.0 . MySQL Database Developer 8.0 . OCI Foundations 2021, 2022, 2023, e 2024. . MySQL Database Service . MySQL Explorer. . SQL Explorer. . Oracle Cloud Data Management 2023
PARCEIROS