Fundamentos de Escenarios de Defectos
7 ejemplos para empezar a modelar escenarios de defectos: 5 básicos y 2 intermedios.
Prerrequisitos
- Base de datos de laboratorio PostgreSQL 18.4.
- Acceso de lectura a patrones de consulta similares a producción (
EXPLAIN,pg_stat_statements).
Ejemplos Básicos
1. Fan-Out Infla Agregados
Una unión de muchos a muchos contada como de uno a muchos duplica los ingresos en los paneles.
-- Mal: la unión de etiquetas multiplica las filas de pedidos
SELECT o.order_id, SUM(oi.amount) AS total
FROM orders o
JOIN order_items oi ON oi.order_id = o.order_id
JOIN order_tags ot ON ot.order_id = o.order_id
GROUP BY o.order_id;
-- Cada artículo de línea repetido por etiqueta- Defecto de modelado: la consulta asume 1:1 entre pedidos y etiquetas.
- Síntoma: los totales de finanzas superan al procesador de pagos por un factor constante.
- Corrección: agregar los artículos de línea en una subconsulta antes de unir las etiquetas.
Relacionado: Explosión de Unión Fan-Out - depuración de cardinalidad
2. Filas Huérfanas Sin Claves Foráneas
La aplicación elimina los padres; los hijos permanecen para siempre.
CREATE TABLE comments (
comment_id bigint PRIMARY KEY,
post_id bigint NOT NULL -- sin cláusula REFERENCES
);
DELETE FROM posts WHERE post_id = 99;
-- Los comentarios con post_id = 99 todavía existen- La FK faltante permite filas huérfanas cuando los errores de la aplicación o el SQL de administración omiten la limpieza.
- Síntoma: la interfaz de usuario muestra comentarios en publicaciones eliminadas o enlaces rotos.
- Corrección: agregar FK con la acción
ON DELETEapropiada.
Relacionado: Claves Foráneas Faltantes - aplicación de integridad
3. Valor Enum Bloqueado Bajo Carga
Agregar un valor enum durante el tráfico mantiene un bloqueo ACCESS EXCLUSIVE brevemente.
CREATE TYPE order_status AS ENUM ('draft', 'placed');
-- Migración posterior bajo carga:
ALTER TYPE order_status ADD VALUE 'shipped';
-- Bloqueo breve; las aplicaciones se ponen en cola en la ruta crítica- Las migraciones de Enum son eventos DDL: dolorosas en columnas de
statuscon QPS alto. - Síntoma: pico de latencia p99 durante el despliegue; reversiones complicadas.
- Corrección:
text+CHECKo estrategia de enum expandir-contraer.
Relacionado: Dolor de Migración de Enum - cambios seguros de enum
4. Marca de Tiempo Sin Zona Horaria Deriva
La hora local almacenada se rompe cuando cambia el horario de verano o los usuarios viajan.
CREATE TABLE meetings (
meeting_id bigint PRIMARY KEY,
starts_at timestamp WITHOUT TIME ZONE -- instante ambiguo
);
INSERT INTO meetings VALUES (1, '2026-03-08 02:30:00');
-- ¿En qué zona horaria? ¿Brecha de horario de verano? Desconocido.timestamp without time zoneno almacena desplazamiento: las aplicaciones globales programan mal las reuniones.- Síntoma: el calendario se desajusta en una hora dos veces al año; los tickets de soporte se agrupan alrededor del horario de verano.
- Corrección:
timestamptzalmacenado en UTC.
Relacionado: Errores de Timestamp Sin Zona Horaria - incidentes de horario de verano
5. Detectar Huérfanas con LEFT JOIN
Consulta estándar de calidad de datos para la aplicación de FK faltantes.
SELECT c.comment_id, c.post_id
FROM comments c
LEFT JOIN posts p ON p.post_id = c.post_id
WHERE p.post_id IS NULL;- Un resultado no vacío significa que la integridad referencial está rota.
- Ejecutar después de migraciones que eliminan FK "temporalmente".
- Agregar al trabajo nocturno de calidad de datos.
Ejemplos Intermedios
6. EXPLAIN Revela Explosión Cartesiana
La estimación de filas salta después de agregar una unión inocente.
EXPLAIN (ANALYZE, BUFFERS)
SELECT COUNT(*) FROM orders o
JOIN order_items oi ON oi.order_id = o.order_id
JOIN order_promotions op ON op.order_id = o.order_id;- Comparar el recuento real de filas con la expectativa ingenua de
orders * items * promotions. - El bucle anidado en un conjunto intermedio inflado señala un error de modelado o de orden de unión.
- Corregir el esquema (tablas de unión) o reescribir la consulta con subconsultas.
Relacionado: Explosión de Unión Fan-Out - patrones de reescritura
7. Post-Mortem a Regla de Lint
Convertir un incidente en prevención automatizada.
-- Verificación de regla de lint pseudo-código: las tablas que terminan en _id deben tener metadatos de FK
SELECT c.conrelid::regclass AS table_name, c.conname
FROM pg_constraint c
WHERE c.contype = 'f';- Documentar la clase de defecto en el runbook: "FK faltante en columnas
*_id". - CI analiza el SQL de migración en busca de
REFERENCESen nuevas columnas con forma de FK. - La lista de verificación de revisión de esquema hace referencia a las páginas de escenarios de defectos.
Relacionado: Mejores Prácticas de Escenarios de Defectos - integración de lint
Versiones de la pila: Esta página fue escrita para PostgreSQL 18.4 (estable 18, mantenimiento 17), pgvector 0.8+, PgBouncer 1.x, Patroni 3.x y PostGIS 3.5+.