Ejercicio 1
- Sin índice: Seq Scan con filtro, coste alto, y filas estimadas ≈ reales si las estadísticas están frescas.
- Con índice: Index Scan (o Bitmap Heap Scan + Index), coste cae un orden de magnitud; si la tabla está en caché,
shared hitdomina en BUFFERS. - Con baja selectividad (status casi uniforme), el planificador puede preferir Seq Scan: leer el índice + saltar a la tabla por el 40% de las filas es más caro que leer todo una vez. El índice brilla con selectividad alta (pocos resultados).
Ejercicio 2
- Esperado: Index Scan en seat por (event_id,...), subplan con Index Scan en reservation_item por seat_id (la UNIQUE condicional crea índice), y un Sort top-N (quicksort en memoria si son pocos). Filas reales vs estimadas con % de desviación razonable.
- El planificador suele elegir planes equivalentes; NOT EXISTS gana en claridad y a veces en plan con anti-join. La conclusión honesta: mide, no adivines — y escribe la que se lee mejor.
Ejercicio 3
- ~51 queries (1 + 50). 2. Con select_related: 1 (JOIN). 3. Añadir event sin arreglar: 51 de nuevo (ahora por evento); con
select_related("user", "event"): 1. 4. Inversas: sin prefetch = N+1; conprefetch_related("items")= 2 queries. Regla: select_related para FK hacia adelante; prefetch para inversas y M2M.
Ejercicio 4
(event_id, state, starts_at)— o(state, starts_at)si siempre filtras state primero; como event_id es igualdad y starts_at rango/orden: igualdades primero, orden último.(gift_card_id, created_at)— igualdad + orden: el índice devuelve el ledger ya ordenado sin Sort.(user_id, created_at DESC)— igualdad + rango reciente.code UNIQUE— además de índice, garantiza que el cupón no se duplique (regla de negocio).(status, expires_at)— ya existe de la 00b; es LA consulta caliente: igualdad + rango. Si el job solo procesa PENDING, valora parcial:CREATE INDEX... WHERE status = 'PENDING_PAYMENT'(más pequeño aún).
Ejercicio 5
- Los INSERTs bajan de velocidad (menos en tablas con muchos índices: cada árbol se inserta también). Números típicos: 10-30% más lento con un índice inútil de texto largo.
- Regla propuesta: un índice se crea con la consulta que lo justifica en la mano (o el constraint de integridad). Sin consulta, sin índice — y con
pg_stat_user_indexesse audita el uso (idx_scan = 0 → candidato a borrar).
Resumen del profesor
- B-tree para igualdad/rango/orden; compuestos: igualdades primero, rango/orden después; los prefijos importan.
- EXPLAIN ANALYZE: scan tipo, estimación vs realidad, Sort en memoria/disco, buffers.
- El N+1 se mata con select_related (JOIN) y prefetch_related (2 queries); se detecta contando queries.
- Cada índice es una hipótesis: se crea con la consulta en la mano, se audita y se borra si nadie lo usa.
Después de la corrección: Lección 10 — Transacciones.