Bases de datos SQL

Índices, transacciones y copias

Lección 8 de 8 · 16 min

Por qué una consulta se vuelve lenta

Sin ayuda, para encontrar los clientes de Bogotá la base de datos lee la tabla entera y va comprobando fila por fila. Con 500 filas es instantáneo; con dos millones, no.

Un índice es lo mismo que el índice de un libro: una estructura ordenada aparte que permite saltar directamente a lo que buscas sin leerlo todo.

Crear índices
-- Sobre una columna que se filtra a menudo
CREATE INDEX idx_clientes_ciudad ON clientes(ciudad);

-- Sobre dos, cuando se filtra por las dos juntas
CREATE INDEX idx_pedidos_cliente_fecha ON pedidos(cliente_id, fecha);

-- Que ademas impida repetidos
CREATE UNIQUE INDEX idx_clientes_email ON clientes(email);

-- Ver los que hay (PostgreSQL)
\di

Un índice no es gratis, y por eso no se indexa «todo por si acaso». Cada índice hay que mantenerlo: acelera las lecturas y ralentiza las escrituras, porque cada INSERT, UPDATE y DELETE tiene que actualizarlo también. Y ocupa disco.

Una tabla con doce índices donde se inserta constantemente puede ir más lenta que sin ninguno. Se indexa lo que de verdad se consulta: las columnas de los WHERE frecuentes y las claves foráneas de los JOIN.

Comprobar si el índice se está usando

Crear un índice no garantiza que la base de datos lo use. Hay una forma de preguntárselo, y existe en los tres motores: pedirle el plan de ejecución.

EXPLAIN: qué piensa hacer la base de datos
-- PostgreSQL y MySQL
EXPLAIN SELECT * FROM clientes WHERE ciudad = 'Bogota';

-- PostgreSQL, ejecutandola de verdad para medir
EXPLAIN ANALYZE SELECT * FROM clientes WHERE ciudad = 'Bogota';
Resultado
Index Scan using idx_clientes_ciudad on clientes  (cost=0.28..8.29 rows=2)
  Index Cond: (ciudad = 'Bogota'::text)

La palabra que hay que buscar en esa salida: Index Scan significa que está usando el índice. Seq Scan -recorrido secuencial- significa que está leyendo la tabla entera. En una tabla grande, eso último es la explicación de la lentitud.

La causa número uno de «tengo el índice y la consulta sigue lenta»: meter la columna dentro de una función en el WHERE.

WHERE YEAR(fecha) = 2026 no puede usar el índice de fecha, porque el índice guarda fechas, no años calculados. Lo mismo con WHERE LOWER(nombre) = 'julia'.

La solución es la de la lección 7: reescribirlo como rango, WHERE fecha >= '2026-01-01' AND fecha < '2027-01-01'. Misma respuesta, y ahora sí usa el índice.

Transacciones: todo o nada

Es la promesa de la lección 1. Un traspaso entre dos cuentas son dos operaciones: descontar de una y abonar en la otra. Si la segunda falla y la primera ya se guardó, el dinero desapareció.

Una transacción agrupa varias operaciones en una sola unidad: se aplican todas o no se aplica ninguna.

Una transacción
BEGIN;                                   -- SQL Server: BEGIN TRANSACTION;

UPDATE cuentas SET saldo = saldo - 500000 WHERE id = 1;
UPDATE cuentas SET saldo = saldo + 500000 WHERE id = 2;

-- Comprobar antes de confirmar
SELECT id, saldo FROM cuentas WHERE id IN (1, 2);

COMMIT;      -- confirma los dos cambios a la vez
-- ROLLBACK;  -- o los deshace los dos

Las tres órdenes

BEGIN

Abre la transacción. A partir de aquí, nada de lo que hagas es definitivo ni lo ven los demás.

COMMIT

Confirma todo el bloque de golpe. Ahora sí es definitivo y visible para todo el mundo.

ROLLBACK

Deshace todo lo hecho desde el BEGIN, como si no hubiera pasado.

Es la red de seguridad del UPDATE peligroso de la lección 5.

Por defecto, cada orden que escribes se confirma sola al terminar -es el modo de confirmación automática-. Por eso un UPDATE sin WHERE no se puede deshacer: ya se confirmó. Abrir la transacción explícitamente es lo que te da la marcha atrás.

Una transacción abierta bloquea filas. Mientras no hagas COMMIT o ROLLBACK, otras sesiones que necesiten esas mismas filas se quedan esperando.

Es la explicación de un clásico: alguien abre una transacción en su cliente, se va a comer, y media empresa reporta que «el sistema está congelado». Las transacciones se abren y se cierran; no se dejan abiertas.

Copias de seguridad

Misma tesis que en los cursos de servidores, y aquí es aún más literal: una copia que nadie ha restaurado no es una copia.

Cada motor trae su herramienta, y hay que usar la suya: copiar los archivos de la base de datos mientras está funcionando produce un archivo corrupto que parece válido.

La herramienta de cada motor
# PostgreSQL
pg_dump -U postgres tienda > tienda_2026-09-07.sql
psql -U postgres -d tienda_restaurada < tienda_2026-09-07.sql

# MySQL
mysqldump -u root -p tienda > tienda_2026-09-07.sql
mysql -u root -p tienda_restaurada < tienda_2026-09-07.sql

# SQL Server (desde el propio motor)
# BACKUP DATABASE tienda TO DISK = 'C:\respaldos\tienda.bak';
# RESTORE DATABASE tienda_restaurada FROM DISK = 'C:\respaldos\tienda.bak';

Una copia que de verdad sirve

  1. 1. Con la herramienta del motor

    Nunca copiando la carpeta de datos con el servicio en marcha: eso da un archivo a medio escribir.

  2. 2. Automática y fechada

    Programada con las tareas del sistema -cron en Linux, el programador en Windows- y con la fecha en el nombre.

    Una copia que hay que acordarse de lanzar no se hace.

  3. 3. Fuera del servidor

    En otra máquina y, mejor, en un destino que el servidor no pueda reescribir. Es lo que la protege de un secuestro de datos.

  4. 4. Restaurada al menos una vez

    Se restaura en otra base de datos -nunca encima de la buena- y se consulta para ver si los datos están.

    Es el único paso que demuestra algo, y es el que casi nadie da.

Cierre: preguntas frecuentes

La base de datos va lenta, ¿por dónde empiezo?

Por identificar qué consulta es la lenta, no por tocar la configuración del servidor.

Después, EXPLAIN sobre esa consulta: si dice recorrido secuencial sobre una tabla grande, ahí está. Casi siempre falta un índice, o hay uno que no se usa por culpa de una función en el WHERE.

¿Índices en todas las claves foráneas?

Casi siempre sí, y es de las mejoras más rentables: son las columnas por las que se hacen los JOIN.

Algunos motores crean automáticamente el índice de la clave primaria pero no el de las foráneas. Conviene comprobarlo.

¿Quién debe poder conectarse a la base de datos?

Lo mínimo. La aplicación se conecta con un usuario propio que no es el administrador, y con permisos solo sobre lo que usa.

Y la base de datos escucha solo donde debe: es exactamente el punto del curso de servidores sobre no exponerla a internet.

¿Y ahora qué practico?

Coge un problema real tuyo -el inventario, los pagos, los clientes- y modélalo: tablas, tipos, restricciones y relaciones.

Ese ejercicio enseña más que cien consultas de ejemplo, porque los datos de verdad nunca encajan a la primera.

Compruébalo tú mismo

Creaste un índice sobre fecha y la consulta WHERE YEAR(fecha) = 2026 sigue lenta. ¿Por qué?

¿Por qué no crear índices en todas las columnas «por si acaso»?

Vas a ejecutar un UPDATE sobre muchas filas y quieres poder deshacerlo. ¿Qué haces?

Hasta dónde llegaste

Sabes crear tablas con reglas que impiden datos inválidos, insertar y consultar, ordenar y paginar, relacionar tablas y volver a unirlas con JOIN, resumir con GROUP BY, manejar fechas y texto esquivando las trampas, y acelerar, proteger y respaldar una base de datos. Y sabes qué cambia entre PostgreSQL, MySQL y SQL Server, que es lo que evita que una consulta migrada devuelva un número equivocado en silencio.

El certificado se saca en el aula. Las preguntas de estas lecciones eran para comprobarte a ti mismo: no guardan nota. La evaluación que certifica se presenta en el Aula Virtual, con tu cuenta, y al aprobarla se emite el certificado a tu nombre.

Por dónde seguir

Con datos que ya sabes consultar, el paso natural es Power BI básico: convertir esas consultas en tableros que alguien pueda leer. Si te toca administrar el servidor donde vive la base de datos, Servidores Linux o Servidores Windows según el sistema. Y Python básico si quieres automatizar lo que hoy consultas a mano.

Terminaste Bases de datos SQL. Presenta la evaluación y reclama tu certificado.

Quiero mi certificado ← Agrupar, fechas y texto