Í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 SÍ 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_loginupdated_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:
type→ref,range,index(bien)ALL→ table scan (mal)key→ índice usadorows→ 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→ altastatus→ 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: