167 lines
6.3 KiB
SQL
167 lines
6.3 KiB
SQL
-- =====================================================================
|
|
-- Script de Optimización para scanning_report_daily_full
|
|
-- Propósito: Mejorar el rendimiento del widget "Comparativa entre Sucursales"
|
|
-- Fecha: 2025-10-21
|
|
-- =====================================================================
|
|
|
|
-- IMPORTANTE: Este script asume que scanning_report_daily_full es una VISTA MATERIALIZADA
|
|
-- Si es una vista regular, se deben crear índices en las tablas subyacentes
|
|
|
|
-- =====================================================================
|
|
-- Paso 1: Verificar si la vista es materializada
|
|
-- =====================================================================
|
|
SELECT
|
|
schemaname,
|
|
matviewname,
|
|
definition
|
|
FROM pg_matviews
|
|
WHERE matviewname = 'scanning_report_daily_full';
|
|
|
|
-- Si el resultado está vacío, es una vista regular, no materializada
|
|
-- En ese caso, usar el script alternativo al final de este archivo
|
|
|
|
-- =====================================================================
|
|
-- Paso 2: Crear índices en la vista materializada (si existe)
|
|
-- =====================================================================
|
|
|
|
-- Índice compuesto principal: NetworkId + DetectionDate
|
|
-- Este índice optimiza las queries más comunes del widget
|
|
CREATE INDEX IF NOT EXISTS idx_scanning_report_network_date
|
|
ON scanning_report_daily_full (network_id, detection_date DESC);
|
|
|
|
-- Índice para filtros por rango de fechas
|
|
CREATE INDEX IF NOT EXISTS idx_scanning_report_detection_date
|
|
ON scanning_report_daily_full (detection_date DESC);
|
|
|
|
-- Índice para filtro por tipo de persona (PasserBy, Visitor)
|
|
CREATE INDEX IF NOT EXISTS idx_scanning_report_person_type
|
|
ON scanning_report_daily_full (person_type);
|
|
|
|
-- Índice compuesto para análisis por red y tipo de persona
|
|
CREATE INDEX IF NOT EXISTS idx_scanning_report_network_person
|
|
ON scanning_report_daily_full (network_id, person_type, detection_date DESC);
|
|
|
|
-- Índice para búsquedas por MAC address (reportes individuales)
|
|
CREATE INDEX IF NOT EXISTS idx_scanning_report_mac
|
|
ON scanning_report_daily_full (mac_address);
|
|
|
|
-- =====================================================================
|
|
-- Paso 3: Configurar auto-refresh de la vista materializada (OPCIONAL)
|
|
-- =====================================================================
|
|
-- NOTA: PostgreSQL no tiene auto-refresh nativo. Esto requiere un job externo.
|
|
-- Ejemplo usando pg_cron (si está instalado):
|
|
|
|
/*
|
|
-- Instalar pg_cron primero:
|
|
CREATE EXTENSION IF NOT EXISTS pg_cron;
|
|
|
|
-- Programar refresh cada hora
|
|
SELECT cron.schedule(
|
|
'refresh-scanning-report',
|
|
'0 * * * *', -- Cada hora en punto
|
|
$$REFRESH MATERIALIZED VIEW CONCURRENTLY scanning_report_daily_full$$
|
|
);
|
|
*/
|
|
|
|
-- Alternativa: Refresh manual (ejecutar según necesidad)
|
|
-- REFRESH MATERIALIZED VIEW CONCURRENTLY scanning_report_daily_full;
|
|
|
|
-- =====================================================================
|
|
-- Paso 4: Analizar estadísticas para el optimizador de queries
|
|
-- =====================================================================
|
|
ANALYZE scanning_report_daily_full;
|
|
|
|
-- =====================================================================
|
|
-- Paso 5: Verificar que los índices se crearon correctamente
|
|
-- =====================================================================
|
|
SELECT
|
|
indexname,
|
|
indexdef
|
|
FROM pg_indexes
|
|
WHERE tablename = 'scanning_report_daily_full'
|
|
ORDER BY indexname;
|
|
|
|
-- =====================================================================
|
|
-- SCRIPT ALTERNATIVO: Si scanning_report_daily_full es una VISTA REGULAR
|
|
-- =====================================================================
|
|
/*
|
|
-- Si es una vista regular, necesitamos crear índices en las tablas base
|
|
-- Asumiendo que la vista consulta la tabla SplashWiFiScanningData:
|
|
|
|
-- Índice compuesto principal
|
|
CREATE INDEX IF NOT EXISTS idx_wifi_scanning_network_date
|
|
ON "SplashWiFiScanningData" ("NetworkId", "CreationTime" DESC);
|
|
|
|
-- Índice para filtros por fecha
|
|
CREATE INDEX IF NOT EXISTS idx_wifi_scanning_creation_time
|
|
ON "SplashWiFiScanningData" ("CreationTime" DESC);
|
|
|
|
-- Índice para MAC address
|
|
CREATE INDEX IF NOT EXISTS idx_wifi_scanning_mac
|
|
ON "SplashWiFiScanningData" ("ClientMac");
|
|
|
|
-- Índice para RSSI (usado en clasificación PasserBy/Visitor)
|
|
CREATE INDEX IF NOT EXISTS idx_wifi_scanning_rssi
|
|
ON "SplashWiFiScanningData" ("NearestApRssi");
|
|
|
|
-- Índice compuesto para queries complejas
|
|
CREATE INDEX IF NOT EXISTS idx_wifi_scanning_network_time_rssi
|
|
ON "SplashWiFiScanningData" ("NetworkId", "CreationTime" DESC, "NearestApRssi");
|
|
|
|
-- Analizar tabla base
|
|
ANALYZE "SplashWiFiScanningData";
|
|
*/
|
|
|
|
-- =====================================================================
|
|
-- Paso 6: Monitoreo de rendimiento (queries útiles)
|
|
-- =====================================================================
|
|
|
|
-- Ver tamaño de la vista/tabla
|
|
SELECT
|
|
pg_size_pretty(pg_total_relation_size('scanning_report_daily_full')) as total_size,
|
|
pg_size_pretty(pg_relation_size('scanning_report_daily_full')) as table_size,
|
|
pg_size_pretty(pg_indexes_size('scanning_report_daily_full')) as indexes_size;
|
|
|
|
-- Ver queries lentas relacionadas con la vista (requiere pg_stat_statements)
|
|
/*
|
|
SELECT
|
|
query,
|
|
calls,
|
|
total_exec_time,
|
|
mean_exec_time,
|
|
max_exec_time
|
|
FROM pg_stat_statements
|
|
WHERE query ILIKE '%scanning_report_daily_full%'
|
|
ORDER BY mean_exec_time DESC
|
|
LIMIT 10;
|
|
*/
|
|
|
|
-- =====================================================================
|
|
-- NOTAS IMPORTANTES
|
|
-- =====================================================================
|
|
/*
|
|
1. Si scanning_report_daily_full es una VISTA MATERIALIZADA:
|
|
- Los índices mejoran las queries de lectura
|
|
- Pero hacen más lento el REFRESH
|
|
- Considerar refresh durante horas de bajo tráfico
|
|
|
|
2. Si es una VISTA REGULAR:
|
|
- Usar el script alternativo para indexar tablas base
|
|
- Los cambios se reflejan inmediatamente
|
|
- No hay overhead de refresh
|
|
|
|
3. Monitoreo post-implementación:
|
|
- Verificar plan de ejecución con EXPLAIN ANALYZE
|
|
- Monitorear pg_stat_user_indexes para uso de índices
|
|
- Ajustar según patrones de uso real
|
|
|
|
4. Mantenimiento:
|
|
- REINDEX periódico si hay muchos UPDATEs/DELETEs
|
|
- VACUUM ANALYZE regular
|
|
- Considerar particionado si la tabla crece mucho (>10M rows)
|
|
*/
|
|
|
|
-- =====================================================================
|
|
-- FIN DEL SCRIPT
|
|
-- =====================================================================
|