Sobre tu PostgreSQL (psql recomendado:
\timing on). No mires solutions.md hasta entregar.
Preparación: genera volumen — 20.000 asientos, 5.000 reservas e ítems (script o generate_series con INSERT...SELECT). Sin volumen no hay planes que leer.
Ejercicio 1 — Sin índice vs con índice
EXPLAIN ANALYZE SELECT * FROM events_payment WHERE reservation_id = 1234;(o tu tabla de pagos). ¿Seq Scan? ¿Coste? ¿Filas estimadas vs reales?- Crea el índice
CREATE INDEX ON events_payment (reservation_id);y repite. Anota la mejora. - Ahora filtra por algo no indexado con baja selectividad (
WHERE status = 'SUCCEEDED'): ¿seq scan o index? ¿Por qué el planificador puede preferir el seq scan incluso con índice?
Ejercicio 2 — Leer el plan como un senior
- Ejecuta la consulta de disponibilidad (07) con
EXPLAIN (ANALYZE, BUFFERS). - Identifica: tipo de scan de cada tabla, si hay Sort y con qué método, filas estimadas vs reales por nodo.
- Cambia el NOT EXISTS por LEFT JOIN + IS NULL y compara planes. ¿Cuál usó el planificador mejor?
Ejercicio 3 — El N+1, cazado y muerto
- En Django shell:
from django.db import connection, reset_queriesy cuenta queries de un loop que imprimar.user.emailpara 50 reservas. Anota el número. - Mismo loop con
select_related("user"). ¿Cuántas queries? - Añade
r.event.titleal loop sin tocar el queryset: ¿cuántas ahora? Arréglalo. - Bonus: relación inversa (
r.items.all()por reserva) con y sinprefetch_related.
Ejercicio 4 — Diseña el índice correcto
Para cada consulta, propon el índice (columnas y orden) y justifica:
WHERE event_id = X AND state = 'PUBLISHED' ORDER BY starts_at(event)WHERE gift_card_id = X ORDER BY created_at(ledger de la 08)WHERE user_id = X AND created_at > now() - interval '30 days'(reservation)WHERE code =?(cupón, se busca en cada checkout — crítica)WHERE status = 'PENDING_PAYMENT' AND expires_at < now()(job de expiración — el más caliente)
Ejercicio 5 — El índice que estorba
- Crea un índice obviamente inútil:
CREATE INDEX ON events_event (description);(texto largo, nunca filtrado). - Mide INSERTs: antes/después con
\timinge INSERT...SELECT de 1.000 filas. ¿Cuánto paga cada insert por mantener el índice? - Bórralo (
DROP INDEX) y registra la regla que aplicarás antes de crear cualquier índice en adelante.
Entrega
Pega planes recortados y números. Con la corrección cerramos la 09; después Lección 10 — Transacciones.