Índices en MySQL: qué son, cuándo usarlos y cuándo NO usarlos


Si trabajas con bases de datos, tarde o temprano te topas con una pregunta clave:

¿Por qué esta consulta tarda tanto si la tabla no es tan grande?

En la mayoría de los casos, la respuesta no está en el servidor… sino en los índices.

En este artículo vamos a ver qué son los índices en MySQL, cómo funcionan realmente, cuándo usarlos, cuándo evitarlos y los errores más comunes que matan el rendimiento sin que te des cuenta.


Antes de comenzar, si aun no te encuentras muy familiarizado con MySQL, puedes comenzar por estos post:

MySQL explicado fácil: qué es, para qué sirve y ejemplos reales

Primeros comandos MySQL que debes memorizar sí o sí


Ahora si podemos continuar...


¿Qué es un índice en MySQL? (explicado fácil)


Un índice es una estructura adicional que MySQL crea para encontrar datos más rápido, sin tener que recorrer toda la tabla fila por fila.

📌 Piensa en un índice como:

  • el índice de un libro
  • no lees todas las páginas
  • vas directo al tema que buscas

Sin índice → MySQL hace un table scan

Con índice → MySQL va directo al dato


Qué problema resuelven los índices


Supongamos esta consulta:

SELECT * 
FROM users 
WHERE email = 'usuario@correo.com';

Si la tabla tiene:

  • 100 filas → no pasa nada
  • 100.000 filas → empieza a doler
  • 1.000.000+ filas → problema serio

Sin índice, MySQL revisa todas las filas.

Con índice en email, MySQL localiza el registro en milisegundos.


Tipos de índices más comunes en MySQL

🔹 PRIMARY KEY

  • Identificador único
  • Siempre indexado
  • Ideal para búsquedas por ID
PRIMARY KEY (id)

🔹 INDEX (normal)

  • Para búsquedas frecuentes
  • No requiere unicidad
CREATE INDEX idx_email ON users(email);

🔹 UNIQUE

  • Garantiza que no haya duplicados
  • Mejora búsquedas + integridad
CREATE UNIQUE INDEX idx_email_unique ON users(email);

🔹 INDEX compuesto

  • Varios campos en un solo índice
  • Muy potente si se usa bien
CREATE INDEX idx_status_created 
ON orders(status, created_at);

⚠️ El orden importa (mucho).



Cómo funciona MySQL con índices (concepto clave)


MySQL usa estructuras tipo B-Tree para la mayoría de índices.

Eso permite:

  • búsquedas rápidas
  • rangos (BETWEEN, >, <)
  • ordenaciones eficientes

Pero ojo:

Un índice no se usa siempre solo por existir.

MySQL decide si usarlo según:

  • cardinalidad
  • selectividad
  • tipo de consulta

Cuándo usar índices (casos claros)


✅ Columnas usadas en WHERE

WHERE email = ?
WHERE status = 'active'

✅ Columnas usadas en JOIN

JOIN orders ON users.id = orders.user_id

✅ Columnas usadas en ORDER BY

ORDER BY created_at DESC

✅ Columnas usadas en GROUP BY

Especialmente en tablas grandes.



Cuándo NO usar índices (esto es clave)


❌ Columnas con pocos valores distintos

Ejemplo:

status = 'active' / 'inactive'

Si el 90 % de los registros tienen el mismo valor:

  • el índice no ayuda
  • MySQL puede ignorarlo

❌ Columnas que cambian constantemente


Ejemplo:

  • last_login
  • updated_at

Cada cambio:

  • actualiza el índice
  • consume CPU y disco

❌ Tablas pequeñas


En tablas con pocas filas:

  • el índice puede ser más lento
  • MySQL hace table scan directamente

El error más común: “indexar todo”


❌ Error típico:

INDEX(name),
INDEX(email),
INDEX(status),
INDEX(created_at),
INDEX(updated_at)

👉 Esto:

  • ralentiza INSERT/UPDATE
  • aumenta tamaño de la tabla
  • no mejora consultas mal pensadas

Regla de oro:

Indexa consultas, no columnas.

Índices compuestos: el truco que pocos usan bien


Un índice compuesto funciona de izquierda a derecha.

INDEX (status, created_at)

✔️ Se usa en:

WHERE status = 'paid'
ORDER BY created_at DESC

❌ NO se usa en:

WHERE created_at = '2024-01-01'

👉 El orden del índice debe reflejar el patrón real de consultas.



Cómo saber si MySQL usa un índice (EXPLAIN)


Nunca optimices a ciegas.

EXPLAIN SELECT * 
FROM users 
WHERE email = 'x@x.com';

Fíjate en:

  • typeref, range, index (bien)
  • ALL → table scan (mal)
  • key → índice usado
  • rows → filas estimadas

👉 EXPLAIN es tu mejor amigo.



Cardinalidad: el concepto que separa juniors de seniors


Cardinalidad = cantidad de valores distintos en una columna.

  • Alta cardinalidad → buen índice
  • Baja cardinalidad → índice inútil

Ejemplo:

  • email → alta
  • status → baja

Por eso no todo merece índice.



Impacto real de los índices en escritura


Esto muchos lo olvidan:

Cada índice:

  • se actualiza en INSERT
  • se actualiza en UPDATE
  • se actualiza en DELETE

👉 Más índices = escritura más lenta

En sistemas con:

  • muchos inserts
  • logs
  • eventos

Hay que ser muy selectivo.



Buenas prácticas reales (checklist)


✔ Indexa columnas usadas en consultas reales

✔ Usa índices compuestos con cabeza

✔ Revisa siempre con EXPLAIN

✔ Elimina índices que no se usan

✔ Piensa en lectura y escritura

✔ Documenta por qué existe cada índice


Ejemplo real de optimización (caso típico)


Antes:

SELECT *
FROM orders
WHERE user_id = 42
ORDER BY created_at DESC
LIMIT 10;

Índice correcto:

INDEX (user_id, created_at)

Resultado:

  • menos filas leídas
  • respuesta inmediata
  • menor carga en servidor

Conclusión: los índices son bisturí, no martillo


Los índices:

  • pueden salvar un sistema
  • o destruir su rendimiento

Usados con criterio:

👉 vuelan

Usados sin pensar:

👉 matan la base de datos lentamente



Tal vez te puede interesar:


Cómo usar LIMIT y OFFSET en MySQL sin matar el rendimiento de tu base de datos