Volver al inicio

Health Score para PostgreSQL: monitoreo de salud

Health Score para PostgreSQL agrega métricas en una puntuación única de 0 a 100 por categorías conexiones, rendimiento, almacenamiento. Detecta combinaciones peligrosas y genera recomendaciones. Adecuado para Grafana y Prometheus.

Un solo Health Score para PostgreSQL: de 150 métricas a un número
Advertisement 728x90

Puntuación de Salud en PostgreSQL: Un indicador compuesto para tu base de datos

La monitorización tradicional con decenas de paneles de Grafana suele provocar fatiga visual: los operadores ignoran gráficos, las alertas o bien generan falsos positivos constantes o se activan demasiado tarde. La Puntuación de Salud resuelve esto al agrupar más de 150 métricas de pg_stat_* en una única puntuación entre 0 y 100. La fórmula considera pesos por categoría y combinaciones peligrosas, permitiendo una evaluación rápida: 95+ es normal, por debajo de 70 requiere acción.

La fórmula base es: Puntuación de Salud = 100 - Σ(penalización_i × peso_i). Las penalizaciones se calculan de forma no lineal, reaccionando a tendencias y anomalías. No se trata de una alerta por umbral, sino de un indicador compuesto similar al Apdex en APM o al EWS en medicina.

Estructura y cálculos por categorías

La Puntuación de Salud se basa en cinco categorías con pesos fijos. Cada una evalúa métricas clave mediante consultas SQL contra las vistas del sistema de PostgreSQL.

Google AdInline article slot

Conexiones (peso 0.20)

Mide la saturación del pool de conexiones y el estado de inactividad:

SELECT 
    count(*) FILTER (WHERE state = 'active') AS conexiones_activas,
    count(*) FILTER (WHERE state = 'idle in transaction') AS inactivas_en_transacción,
    (SELECT setting::int FROM pg_settings WHERE name = 'max_connections') AS max_conexiones,
    now() - min(xact_start) AS edad_máxima_transacción
FROM pg_stat_activity
WHERE pid != pg_backend_pid();

La penalización crece exponencialmente tras el 80% de uso. Las sesiones inactivas en transacción con más de 30 segundos acumulan una penalización adicional, ya que bloquean el autovacío y contribuyen al bloat.

Rendimiento (peso 0.25)

Se centra en la experiencia del usuario: tasa de acierto en caché y consultas lentas.

Google AdInline article slot
-- Tasa de acierto en caché
SELECT 
    round(100.0 * sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read), 0), 2) AS tasa_acierto_caché
FROM pg_statio_user_tables;

-- Consultas lentas
SELECT count(*), round(avg(mean_exec_time)::numeric, 2)
FROM pg_stat_statements
WHERE mean_exec_time > 1000 AND calls > 10;

Una tasa de acierto inferior al 95% desencadena una penalización; por debajo del 90% es crítica. El tiempo de ejecución se compara con líneas base históricas para detectar anomalías.

Almacenamiento (peso 0.20)

Monitorea tuplas muertas y bloat:

SELECT 
    schemaname, relname, n_dead_tup, n_live_tup,
    round(100.0 * n_dead_tup / nullif(n_live_tup + n_dead_tup, 0), 2) AS ratio_muertas,
    pg_size_pretty(pg_total_relation_size(relid))
FROM pg_stat_user_tables
WHERE n_live_tup + n_dead_tup > 10000
ORDER BY ratio_muertas DESC LIMIT 20;

El bloat se evalúa usando pgstattuple o heurísticas basadas en relpages. El uso de disco se compara con los límites del sistema de archivos.

Google AdInline article slot

Replicación (peso 0.15)

Verifica el retraso en réplicas:

SELECT application_name, state, (sent_lsn - replay_lsn) AS lag_bytes,
    write_lag, flush_lag, replay_lag
FROM pg_stat_replication;

Un retraso superior a 1 MB o 5 segundos genera penalización. La ausencia de réplicas no penaliza esta categoría.

Mantenimiento (peso 0.20)

Rastrea el progreso del vaciado y la edad de XID:

-- Edad de XID
SELECT datname, age(datfrozenxid), 2147483648 - age(datfrozenxid)
FROM pg_database ORDER BY age(datfrozenxid) DESC;

-- Edad del vaciado
SELECT schemaname, relname, now() - greatest(last_vacuum, last_autovacuum) AS edad_vaciado
FROM pg_stat_user_tables WHERE n_live_tup > 10000
ORDER BY edad_vaciado DESC NULLS FIRST LIMIT 20;

Una edad de XID superior a 1.500 millones genera una alta penalización por riesgo de sobrecarga.

Lógica de pesos e interpretación

Los pesos se eligieron empíricamente: Rendimiento lidera con 0.25 porque afecta directamente a la experiencia del usuario. Conexiones y Mantenimiento (0.20) son puntos de fallo rápidos. Replicación (0.15) es opcional.

  • 95+: Condición estable.
  • 70–94: Monitorear, planificar correcciones.
  • 40–69: Acción inmediata requerida.
  • <40: Estado de incidente.

Diagnóstico automático con recomendaciones

La Puntuación de Salud incluye una lista priorizada de problemas:

  • ALTA: Tabla con >40% de tuplas muertas y vaciado antiguo de 4 días — ejecutar VACUUM ANALYZE, ajustar autovacuum_vacuum_scale_factor.
  • MEDIA: Retraso de replicación >500 ms — revisar carga de réplica, wal_receiver_timeout.
  • BAJA: Tasa de acierto <99% — aumentar shared_buffers hasta un 25% de la RAM.

Las recomendaciones se generan mediante reglas, incluyendo verificaciones contra umbrales de autovacío.

SELECT relname, n_dead_tup > (n_live_tup * current_setting('autovacuum_vacuum_scale_factor')::float + current_setting('autovacuum_vacuum_threshold')::float) AS vaciado_requerido
FROM pg_stat_user_tables;

Conclusiones clave

  • La Puntuación de Salud agrega métricas ponderadas, revelando combinaciones ocultas como conexión inactiva + bloat que las alertas por umbral pasan por alto.
  • La fórmula no lineal ofrece advertencias tempranas antes de alcanzar umbrales críticos.
  • Se integra con Prometheus/Grafana mediante postgres_exporter.
  • El diagnóstico automático entrega recomendaciones accionables con ejemplos reales de SQL.
  • Escalable: compara tendencias históricas para detectar anomalías.

— Editorial Team

Advertisement 728x90

Leer después