Módulo 03 // Unidad 02

Bases de datos eficientes

Esquemas, índices y consultas que no hacen trabajar al servidor de más

Unidad para alumnos del curso

Comprobando tu sesión…

Inicia sesión con la cuenta de Google con la que estás matriculado para ver esta unidad.

Esa cuenta no tiene acceso a este curso. Prueba con otra.

No se ha podido cargar el inicio de sesión de Google. Comprueba la conexión o si algún bloqueador lo impide, y recarga la página.

En la mayoría de aplicaciones web, el código de la API pasa buena parte del tiempo esperando a la base de datos. Es el sitio donde una mala decisión se nota más: una consulta sin índice sobre una tabla grande puede costar miles de veces más que la misma consulta bien planteada. Esta unidad repasa las tres cosas que controlas: el esquema, los índices y las consultas.

1 // El trabajo invisible de una consulta

Cuando escribes SELECT y recibes filas, el servidor de base de datos ha tenido que analizar la consulta, decidir un plan de ejecución, leer páginas de datos del disco o de la memoria, filtrar, ordenar y enviar el resultado. Todo eso es CPU, memoria y operaciones de disco.

Además, las bases de datos son servicios que se dimensionan por su pico: si unas consultas ineficientes obligan a tener un servidor con el doble de memoria y CPU, ese servidor más grande estará encendido todo el día, no sólo en el momento de la consulta lenta. Por eso la eficiencia en la base de datos ahorra doblemente: energía por consulta y tamaño de la infraestructura.

2 // El esquema: guardar lo justo

El diseño de las tablas decide cuánto ocupa cada fila, y el tamaño de las filas decide cuántas caben en memoria y cuántas hay que leer del disco.

Decisión Menos eficiente Más eficiente
Un estado con pocos valores VARCHAR(255) con texto repetido TINYINT o ENUM
Una fecha Texto '2026-09-17' DATE
Un identificador numérico BIGINT cuando nunca pasará de miles INT o menor, según el rango real
Datos que casi nunca se leen En la tabla principal, junto a lo que se consulta siempre En una tabla aparte
Ficheros e imágenes Guardados como BLOB en la tabla En almacenamiento de objetos, con la ruta en la tabla

La normalización que has estudiado evita duplicar datos y ahorra espacio. A veces se desnormaliza a propósito, copiando un dato para evitar un JOIN costoso que se repite millones de veces. Ninguna de las dos opciones es siempre la buena: la pregunta es qué consulta se ejecuta más y qué diseño la abarata.

Guardar «por si acaso» también tiene huella. Registros que nadie consulta, tablas de auditoría sin límite o históricos de hace diez años ocupan disco, se incluyen en cada copia de seguridad y hacen más lentas las consultas. Define cuánto tiempo necesitas cada dato y borra o archiva lo que sobra.

3 // Índices: el atajo con coste

Un índice es una estructura adicional, normalmente un árbol B, que permite encontrar filas por el valor de una columna sin recorrer la tabla entera. Es como el índice de un libro: en lugar de leer las 800 páginas, vas directo a la que buscas.

SIN ÍNDICE FRENTE A CON ÍNDICE SIN ÍNDICE · lee todas las filas 5.000.000 lecturas → 20 filas útiles CON ÍNDICE · árbol B raíz nivel 2 hoja 3 saltos + 20 filas → unas 25 lecturas EXPLAIN te dice cuál de los dos caminos está siguiendo tu consulta
A la izquierda, sin índice, hay que leer todas las filas para encontrar unas pocas. A la derecha, el árbol del índice llega a ellas en tres o cuatro saltos, aunque la tabla tenga millones de filas.

Una tabla pedidos tiene 5 millones de filas y la consulta más frecuente busca los pedidos de un cliente concreto: WHERE cliente_id = 1234. Cada cliente tiene unos 20 pedidos.

  1. Sin índice: el motor recorre las 5.000.000 de filas y se queda con 20.
  2. Con índice en cliente_id: el árbol B, con cientos de claves por nodo, tiene 3 o 4 niveles. El motor baja por el árbol y lee unas 25 entradas en total, entre nodos y filas.
  3. Proporción: del orden de 200.000 veces menos lecturas.
La misma consulta pasa de leer millones de filas a leer unas decenas. Si se ejecuta miles de veces al día, el índice decide si basta un servidor pequeño o hace falta uno grande.

Pero los índices no son gratis:

  • Cada escritura es más cara: un INSERT o un UPDATE tiene que actualizar la tabla y todos sus índices.
  • Ocupan disco y memoria: en tablas muy indexadas, los índices pueden ocupar más que los propios datos.
  • Un índice sin uso es puro coste.

La herramienta para decidir es EXPLAIN: antepuesta a una consulta en MySQL, muestra el plan de ejecución, si se usa algún índice y cuántas filas estima leer. Si ves que recorre la tabla completa en una consulta frecuente, ahí hay trabajo.

4 // Consultas que no leen de más

Con el esquema y los índices bien, queda la forma de preguntar. Los errores más comunes:

  • SELECT *: trae todas las columnas aunque uses dos. Más lectura, más memoria, más datos por la red. Pide sólo las columnas que necesitas.
  • Las N+1 consultas: obtener 100 pedidos y lanzar después una consulta por cada uno para buscar su cliente. Son 101 viajes a la base de datos donde bastaba uno con JOIN. Los ORM lo provocan con facilidad si no se configura la carga de relaciones.
  • Filtrar en el código lo que podía filtrar la base de datos: traer 10.000 filas para quedarte con 10 en JavaScript o en PHP.
  • Funciones sobre columnas indexadas: WHERE YEAR(fecha) = 2026 impide usar el índice de fecha; WHERE fecha >= '2026-01-01' AND fecha < '2027-01-01' sí lo aprovecha.
  • Paginar con OFFSET enorme: LIMIT 20 OFFSET 100000 obliga a leer y descartar 100.000 filas. Paginar por clave («los siguientes a este id») evita ese trabajo.

El temario menciona también Elasticsearch, muy usado para búsquedas de texto. Los principios son los mismos con otro vocabulario: definir el mapping a mano en lugar de dejar que lo adivine, no indexar campos por los que nunca se busca, pedir sólo los campos necesarios en _source y no crear muchos más shards de los que el volumen de datos justifica, porque cada uno consume memoria aunque esté casi vacío.

Una base de datos eficiente guarda lo justo, indexa lo que se consulta y pregunta sólo por lo que necesita. Usa EXPLAIN antes de dar por buena una consulta frecuente: es la forma más barata de ahorrar servidores.

Autoevaluación

¿Por qué un índice reduce el consumo de una consulta?
Porque evita leer filas que no interesan. Sin índice, la base de datos recorre la tabla entera para encontrar unas pocas filas; con un índice en árbol, llega a ellas en unos pocos saltos. Menos lecturas significan menos disco, menos CPU y menos memoria ocupada por cada consulta.
Si los índices aceleran las consultas, ¿por qué no indexar todas las columnas?
Porque cada índice cuesta al escribir y ocupa espacio. Cada inserción o actualización tiene que modificar también todos los índices de la tabla, y cada índice ocupa disco y memoria. Un índice que ninguna consulta usa es trabajo y almacenamiento sin ningún beneficio.
¿Qué es el problema de las N+1 consultas y por qué desperdicia recursos?
Es hacer una consulta para obtener una lista y luego otra por cada elemento de esa lista. Para 100 pedidos se lanzan 101 consultas, cada una con su viaje de red y su trabajo de análisis en el servidor. Una sola consulta con un JOIN, o una con IN, obtiene lo mismo con una fracción del trabajo.