Introducción a los Eventos del Sistema
Publicado: Noviembre 2023
El sistema Tuxeria implementa 3 eventos programados que ejecutan tareas de mantenimiento y análisis de forma automática y periódica. Estos eventos trabajan sobre las tablas auxiliares creadas previamente para optimización.
Características principales de los eventos:
- Ejecución automática según programación definida
- Mantenimiento de datos históricos y estadísticos
- Identificación de patrones de comportamiento
- Limpieza y organización de datos automatizada
Importante: Para que los eventos funcionen, debe estar activado el event scheduler:
SET GLOBAL event_scheduler = ON;
Evento 1: topclientes
Programación: Cada 1 minuto
Código completo:
DROP EVENT IF EXISTS topclientes;
DELIMITER //
CREATE EVENT topclientes
ON SCHEDULE EVERY 1 MINUTE
DO
BEGIN
TRUNCATE TABLE top_clientes;
INSERT INTO top_clientes (nombre, cant_pedidos, cant_pizzas)
SELECT
C.nombre,
COUNT(DISTINCT P.num_pedido) AS Pedidos_Mes_Anterior,
IFNULL(SUM(LP.unidades), 0) AS Unidades_Mes_Anterior
FROM Cliente C
LEFT JOIN Pedido P
ON C.DNI = P.dni_cliente
AND P.fechahora >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND P.fechahora < DATE_FORMAT(CURDATE(), '%Y-%m-01')
LEFT JOIN LineaPedido LP
ON P.num_pedido = LP.num_pedido
GROUP BY C.DNI, C.nombre
HAVING Pedidos_Mes_Anterior >= 5 OR Unidades_Mes_Anterior >= 9
ORDER BY Pedidos_Mes_Anterior DESC, C.nombre;
END //
Funcionamiento:
- Frecuencia: Se ejecuta cada minuto (probablemente para testing, en producción sería mensual)
- Objetivo: Identificar clientes VIP del mes anterior
- Criterios: Clientes con 5+ pedidos O 9+ pizzas en el mes anterior
Lógica del filtro temporal:
P.fechahora >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND P.fechahora < DATE_FORMAT(CURDATE(), '%Y-%m-01')
Este filtro selecciona pedidos del mes completo anterior (ej: si hoy es 15/11, selecciona pedidos de octubre).
Ejemplo de datos generados:
| nombre |
cant_pedidos |
cant_pizzas |
| Juan Pérez |
7 |
12 |
| María García |
5 |
8 |
| Carlos López |
4 |
10 |
Carlos López aparece porque tiene 10 pizzas (cumple el segundo criterio).
Evento 2: clientesanti
Programación: Cada 10 minutos
Código completo (simplificado):
CREATE EVENT clientesanti
ON SCHEDULE EVERY 10 MINUTE
ON COMPLETION PRESERVE
ENABLE
DO
BEGIN
-- Declaración de variables y cursor
DECLARE c CURSOR FOR
SELECT c.*, p.fechahora
FROM Cliente c
JOIN Pedido p ON c.DNI = p.dni_cliente
GROUP BY c.DNI
HAVING TIMESTAMPDIFF(YEAR, MAX(p.fechahora), CURDATE()) >= 1;
-- Lógica con cursor para procesar cada cliente
-- ...
TRUNCATE TABLE clientes_antiguos;
-- Inserta clientes inactivos en la tabla de archivo
END //
Funcionamiento:
- Frecuencia: Cada 10 minutos
- Objetivo: Archivar clientes inactivos por más de 1 año
- Técnica: Usa CURSOR para procesamiento fila por fila
- ON COMPLETION PRESERVE: El evento no se elimina después de ejecutarse
- ENABLE: El evento se crea activado
Lógica del cursor:
- Selecciona clientes que han hecho al menos un pedido
- Agrupa por DNI para obtener el último pedido de cada cliente
- Filtra aquellos cuyo último pedido fue hace 1 año o más
- Procesa cada resultado con un cursor
Condición clave:
TIMESTAMPDIFF(YEAR, MAX(p.fechahora), CURDATE()) >= 1
Esta condición calcula la diferencia en años entre la fecha del último pedido y la fecha actual.
Problema potencial:
El evento no considera clientes sin pedidos porque hace JOIN con la tabla Pedido. Un cliente registrado hace más de 1 año pero sin pedidos no sería archivado.
Evento 3: clientessinped
Programación: Cada 10 minutos
Código completo (simplificado):
CREATE EVENT clientessinped
ON SCHEDULE EVERY 10 MINUTE
ON COMPLETION PRESERVE
ENABLE
DO
BEGIN
-- Cursor para clientes nuevos sin pedidos
DECLARE c CURSOR FOR
SELECT *
FROM Cliente
WHERE TIMESTAMPDIFF(MONTH, fecha_alta, CURDATE()) >= 1
AND ped_realizados = 0;
-- Procesamiento con cursor
-- ...
TRUNCATE TABLE clientes_nuevossinped;
-- Inserta clientes nuevos sin pedidos
END //
Funcionamiento:
- Frecuencia: Cada 10 minutos
- Objetivo: Identificar clientes registrados hace 1+ mes sin pedidos
- Criterios:
- Registrado hace 1 mes o más
- Ningún pedido realizado (ped_realizados = 0)
Condiciones de filtrado:
TIMESTAMPDIFF(MONTH, fecha_alta, CURDATE()) >= 1
AND ped_realizados = 0
Esta lógica aprovecha el campo ped_realizados que mantienen los triggers, evitando un JOIN costoso con la tabla Pedido.
Propósito de negocio:
Identificar clientes potenciales que se registraron pero no completaron ninguna compra, útil para campañas de remarketing o seguimiento comercial.
Análisis Comparativo de Eventos
Resumen de funcionalidades:
| Evento |
Frecuencia |
Tabla Destino |
Propósito |
| topclientes |
1 minuto |
top_clientes |
Identificar clientes VIP |
| clientesanti |
10 minutos |
clientes_antiguos |
Archivar clientes inactivos |
| clientessinped |
10 minutos |
clientes_nuevossinped |
Identificar leads no convertidos |
Uso de Cursors vs Consultas Directas:
- topclientes: Usa consulta directa (más eficiente para datos agregados)
- clientesanti/clientessinped: Usan cursors (necesario para procesamiento fila por fila con lógica compleja)
Optimizaciones posibles:
- topclientes: Cambiar frecuencia a mensual en producción
- clientesanti: Reemplazar cursor con INSERT...SELECT directo
- clientessinped: Ya está optimizado al usar ped_realizados
Versión optimizada de clientesanti:
-- Sin cursor, más eficiente
CREATE EVENT clientesanti_optimizado
ON SCHEDULE EVERY 1 DAY
DO
BEGIN
TRUNCATE TABLE clientes_antiguos;
INSERT INTO clientes_antiguos
SELECT c.*, MAX(p.fechahora) as ultimo_pedido
FROM Cliente c
JOIN Pedido p ON c.DNI = p.dni_cliente
GROUP BY c.DNI, c.nombre, c.direccion, c.poblacion,
c.telefono, c.email, c.fecha_alta,
c.ped_realizados, c.pizzastotales
HAVING TIMESTAMPDIFF(YEAR, MAX(p.fechahora), CURDATE()) >= 1;
END //
Integración con el Sistema Completo
Flujo de datos completo:
- En tiempo real: Triggers actualizan contadores en Cliente y Pizza
- Cada minuto: topclientes recalcula clientes VIP
- Cada 10 minutos:
- clientesanti archiva inactivos
- clientessinped identifica leads fríos
Ventajas de esta arquitectura:
- Separación de responsabilidades: Triggers para tiempo real, eventos para batch
- Rendimiento: Cálculos pesados se hacen en horarios controlados
- Históricos: Tablas auxiliares mantienen snapshots periódicos
- Escalabilidad: Fácil ajustar frecuencias según necesidades
Casos de uso empresarial:
- Marketing: Campañas para clientes VIP o recuperación de inactivos
- Ventas: Seguimiento de leads no convertidos
- Análisis: Tendencias mensuales de clientes más valiosos
- Operaciones: Limpieza automatizada de base de datos
Conclusión
Los eventos programados en Tuxeria completan el ecosistema de automatización junto con los triggers:
Triggers vs Eventos:
| Aspecto |
Triggers |
Eventos |
| Activación |
Por operaciones DML |
Por tiempo/cron |
| Frecuencia |
En tiempo real |
Periódica |
| Propósito |
Mantener consistencia |
Mantenimiento/análisis |
| Ejemplo |
Actualizar contadores |
Generar reportes |
Recomendaciones para producción:
- Ajustar frecuencias según necesidades reales (1 minuto es excesivo para topclientes)
- Monitorizar ejecución de eventos en logs
- Considerar backups antes de TRUNCATE en tablas críticas
- Implementar manejo de errores en eventos
El sistema demuestra una arquitectura completa donde las alteraciones de tablas, triggers y eventos trabajan conjuntamente para crear un sistema autónomo y eficiente.