BEGIN
Abre la transacción. A partir de aquí, nada de lo que hagas es definitivo ni lo ven los demás.
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.
-- 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)
\diUn í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.
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.
-- PostgreSQL y MySQL
EXPLAIN SELECT * FROM clientes WHERE ciudad = 'Bogota';
-- PostgreSQL, ejecutandola de verdad para medir
EXPLAIN ANALYZE SELECT * FROM clientes WHERE ciudad = 'Bogota';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.
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.
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 dosAbre la transacción. A partir de aquí, nada de lo que hagas es definitivo ni lo ven los demás.
Confirma todo el bloque de golpe. Ahora sí es definitivo y visible para todo el mundo.
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.
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.
# 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';Nunca copiando la carpeta de datos con el servicio en marcha: eso da un archivo a medio escribir.
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.
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.
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.
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.
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.
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.
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.
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?
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.
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