/

/

Cómo Optimizar Consultas SQL: Guía de Performance

Content

Cómo Optimizar Consultas SQL: Guía de Performance

Cómo Optimizar Consultas SQL: Guía de Performance

Introducción

Una consulta SQL mal optimizada puede tardar minutos cuando debería tomar milisegundos. Aprender a optimizar consultas es una habilidad crítica para cualquier desarrollador o analista de datos.

Diagnóstico: EXPLAIN

El primer paso para optimizar es entender cómo MySQL ejecuta tu consulta:

EXPLAIN SELECT * FROM pedidos WHERE cliente_id = 123;

Interpretando EXPLAIN

| Campo | Significado | Valor Ideal |

|-------|-------------|-------------|

| type | Tipo de acceso | const, eq_ref, ref (evitar ALL) |

| possible_keys | Índices disponibles | Debería mostrar índices |

| key | Índice usado | No NULL |

| rows | Filas a examinar | Menor número posible |

| Extra | Información adicional | Evitar "Using filesort", "Using temporary" |


---

Los 10 Problemas Más Comunes y Sus Soluciones

1. SELECT *

Problema:

SELECT * FROM usuarios;

Solución:

SELECT id, nombre, email FROM usuarios;

Por qué: Solo trae las columnas necesarias, reduce I/O y uso de memoria.

---

2. Falta de Índices

Problema:

SELECT * FROM pedidos WHERE fecha = '2024-01-15';
 -- Full table scan sin índice

Solución:

CREATE INDEX idx_fecha ON pedidos(fecha);

Cuándo Crear Índices

  • Columnas en WHERE frecuentemente

  • Columnas en JOIN

  • Columnas en ORDER BY

  • Columnas con alta cardinalidad (muchos valores únicos)

Cuándo NO Crear Índices

  • Tablas pequeñas (<1000 filas)

  • Columnas con pocos valores únicos (ej: género, boolean)

  • Columnas que cambian frecuentemente

---

3. Funciones en WHERE

Problema:

SELECT * FROM usuarios
 WHERE YEAR(fecha_registro) = 2024;
 -- No puede usar índice

Solución:

SELECT * FROM usuarios
 WHERE fecha_registro >= '2024-01-01'
  AND fecha_registro < '2025-01-01';
 -- Puede usar índice en fecha_registro

---

4. OR en WHERE

Problema:

SELECT * FROM productos
 WHERE categoria = 'Electrónica' OR precio > 1000;
 -- Difícil de optimizar

Solución:

SELECT * FROM productos WHERE categoria = 'Electrónica'
 UNION
 SELECT * FROM productos WHERE precio > 1000;

---

5. NOT IN con Subconsulta Grande

Problema:

SELECT * FROM clientes
 WHERE id NOT IN (SELECT cliente_id FROM pedidos);

Solución:

SELECT c.*
 FROM clientes c
 LEFT JOIN pedidos p ON c.id = p.cliente_id
 WHERE p.id IS NULL;

---

6. LIKE con Comodín al Inicio

Problema:

SELECT * FROM productos WHERE nombre LIKE '%laptop%';
 -- Full table scan

Soluciones:

  • Full-text search para búsquedas de texto

  • Índices de texto completo

  • Elasticsearch para búsquedas complejas

-- Con Full-Text Index
 ALTER TABLE productos ADD FULLTEXT(nombre);
 SELECT * FROM productos WHERE MATCH(nombre) AGAINST('laptop');

---

7. JOINs sin Índices

Problema:

SELECT * FROM pedidos p
 JOIN clientes c ON p.cliente_id = c.id;
 -- Lento si no hay índice en cliente_id

Solución:

CREATE INDEX idx_cliente ON pedidos(cliente_id);

---

8. ORDER BY sin Índice

Problema:

SELECT * FROM productos ORDER BY precio DESC;
 -- "Using filesort" en EXPLAIN

Solución:

CREATE INDEX idx_precio ON productos(precio);

---

9. Subconsultas Correlacionadas

Problema:

SELECT *,
  (SELECT COUNT(*) FROM pedidos WHERE cliente_id = c.id) as num_pedidos
 FROM clientes c;
 -- Ejecuta subconsulta por cada fila

Solución:

SELECT c.*, COALESCE(p.num_pedidos, 0) as num_pedidos
 FROM clientes c
 LEFT JOIN (
  SELECT cliente_id, COUNT(*) as num_pedidos
  FROM pedidos
  GROUP BY cliente_id
 ) p ON c.id = p.cliente_id;

---

10. DISTINCT Innecesario

Problema:

SELECT DISTINCT cliente_id FROM pedidos WHERE fecha > '2024-01-01';

Alternativa más eficiente:

SELECT cliente_id FROM pedidos WHERE fecha > '2024-01-01'
 GROUP BY cliente_id;

---

Índices Compuestos

Para consultas con múltiples condiciones:

-- Consulta frecuente
 SELECT * FROM pedidos
 WHERE cliente_id = 123 AND estado = 'completado'
 ORDER BY fecha DESC;


Regla del Prefijo Izquierdo

Un índice (A, B, C) puede usarse para:

  • Consultas con A

  • Consultas con A y B

  • Consultas con A, B y C

  • NO para consultas solo con B o C


---

Optimización de Queries Específicos

Paginación Eficiente

Problema (offset grande):

SELECT * FROM productos ORDER BY id LIMIT 100000, 20;
 -- Muy lento con offset grande

Solución (keyset pagination):

SELECT * FROM productos
 WHERE id > 100000
 ORDER BY id
 LIMIT 20;

COUNT Optimizado

Problema:

SELECT COUNT(*) FROM tabla_grande WHERE condicion;

Soluciones:

  • Usar COUNT aproximado si es aceptable

  • Mantener contadores en tabla separada

  • Cachear resultados

---

Herramientas de Profiling

MySQL

SET profiling = 1;
 SELECT * FROM tabla WHERE condicion;
 SHOW PROFILE FOR QUERY 1;

Slow Query Log

-- Habilitar logging de queries lentas
 SET GLOBAL slow_query_log = 'ON';
 SET GLOBAL long_query_time = 2; -- segundos

---

Checklist de Optimización

1. [ ] ¿Estoy seleccionando solo las columnas necesarias?

2. [ ] ¿Las columnas en WHERE tienen índices?

3. [ ] ¿Evité funciones en columnas indexadas?

4. [ ] ¿Los JOINs usan columnas indexadas?

5. [ ] ¿Revisé el plan de ejecución con EXPLAIN?

6. [ ] ¿Consideré índices compuestos para queries frecuentes?

7. [ ] ¿La paginación es eficiente?

8. [ ] ¿Las subconsultas pueden reescribirse como JOINs?


---

Conclusión

La optimización de SQL es un equilibrio entre legibilidad, mantenibilidad y performance. Siempre mide antes y después de optimizar para asegurar mejoras reales.

---

Tip: Usa AI2sql para generar consultas optimizadas automáticamente. La IA considera mejores prácticas de performance al crear el SQL.

Share this

More Articles