Pregunta y contexto
Un clúster de PostgreSQL 18 atiende una tabla de pedidos con alto volumen de actualizaciones y tablas de archivo de baja frecuencia. Se acumulan tuplas muertas, las consultas se ralentizan y se producen picos de I/O en disco. Diseña la gestión de capacidad de los workers de autovacuum y explica autovacuum_worker_slots, autovacuum_max_workers, las configuraciones de tabla, el mantenimiento paralelo y las compensaciones en incidentes.
Lo que evalúa el entrevistador
- Si separas la capacidad de workers, los workers concurrentes, los umbrales de activación y el paralelismo por comando.
- Si explicas
autovacuum_worker_slotsen PostgreSQL 18 y su límite de ajuste en tiempo de ejecución. - Si utilizas vistas de progreso, tuplas muertas, antigüedad de transacciones y métricas de I/O para localizar cuellos de botella.
- Si priorizas la protección contra el wraparound de IDs de transacción frente a la latencia y la presión de disco.
Preguntas clarificadoras iniciales
Carga de trabajo
¿Cuáles son las tasas de actualización, eliminación e inserción por base de datos y tabla? ¿Tienen las tablas activas muchos índices, transacciones largas o eliminaciones masivas? ¿El SLA se enfoca en la latencia de consultas, el rendimiento de escritura o el crecimiento del disco?
Límites de recursos
¿Cuáles son los límites de CPU, I/O, memoria y crecimiento de disco? ¿Cómo están configurados max_worker_processes, max_parallel_workers, maintenance_work_mem y los límites del contenedor o VM?
Riesgo y recuperación
¿Se está acercando el clúster al wraparound de IDs de transacción? ¿Es posible ejecutar VACUUM manual o intercambios de particiones fuera de las horas pico? ¿Qué tablas pueden reducir temporalmente sus escrituras y qué evidencias deben permanecer auditables?
Una respuesta en 30 segundos
Cuantificaría el crecimiento de tuplas muertas, el retraso de autovacuum, la antigüedad de transacciones y la I/O por tabla y base de datos, para luego dimensionar los slots de workers y la concurrencia normal. Las tablas activas reciben factores de escala más bajos y umbrales adecuados; las tablas frías evitan escaneos innecesarios. Antes de incrementar la concurrencia, verificaría la CPU, la I/O y la memoria de mantenimiento, utilizando después las vistas de progreso para comprobar la reducción de la acumulación de tareas. El riesgo de wraparound es la máxima prioridad; la limitación de tasas y el mantenimiento manual focalizado son controles de emergencia acotados.
Solución a profundidad
1. Mapear la jerarquía de recursos
autovacuum_worker_slots reserva slots de backend para workers de autovacuum al iniciar el servidor. PostgreSQL 18 suele tener un valor predeterminado de 16 slots, sujeto al soporte del kernel. autovacuum_max_workers limita los procesos de autovacuum concurrentes y no puede superar el grupo de slots efectivo. max_worker_processes, la CPU y la I/O siguen siendo recursos compartidos, por lo que no es posible ajustar un único parámetro de forma aislada.
2. Diseñar concurrencia por capas
Define autovacuum_worker_slots como el grupo de capacidad para el pico que puedas permitirte, y luego utiliza autovacuum_max_workers para la concurrencia normal. PostgreSQL 18 permite modificar autovacuum_max_workers en tiempo de ejecución hasta el límite de slots, mientras que los slots en sí requieren reiniciar el servidor. Antes de aumentar la capacidad, reserva procesos en segundo plano, conexiones y semáforos del sistema operativo.
3. Establecer activadores específicos por tabla
Los umbrales globales proporcionan una base de seguridad. Las tablas activas pueden reducir autovacuum_vacuum_scale_factor o establecer un autovacuum_vacuum_threshold más adecuado; las tablas con muchas inserciones también necesitan autovacuum_vacuum_insert_threshold. Calcula las configuraciones personalizadas de tabla a partir del crecimiento de tuplas muertas y el tamaño de la tabla, de modo que las tablas pequeñas no se retrasen y las grandes no se escaneen con demasiada frecuencia.
4. Limitar los recursos de un único VACUUM
El VACUUM regular puede ejecutarse junto con lecturas y escrituras, pero genera I/O. max_parallel_maintenance_workers se aplica a la construcción de índices y a VACUUM sin FULL; los workers reales también están limitados por max_worker_processes y max_parallel_workers. maintenance_work_mem se aplica al comando de utilidad en su totalidad, mientras que la CPU y la I/O pueden incrementarse con el paralelismo.
5. Gestionar wraparound y transacciones largas
Incluso cuando el autovacuum regular está deshabilitado, PostgreSQL inicia el trabajo necesario para evitar el wraparound de IDs de transacción. Monitorea la antigüedad de la transacción más antigua, el progreso del freeze y las transacciones largas que bloquean a VACUUM. La protección contra wraparound no puede anularse mediante políticas de retraso ordinarias. Si es necesario, finaliza el bloqueador, pausa tareas por lotes de baja prioridad y realiza el mantenimiento de la tabla objetivo.
6. Construir observabilidad accionable
Utiliza pg_stat_progress_vacuum para fase, bloques de heap, bloques limpiados, ciclos de índices, bytes de tuplas muertas y retraso por costo. Combínalo con valores de pg_stat_all_tables como n_dead_tup, last_autovacuum, last_autoanalyze, tamaño de tabla y antigüedad de transacciones para estimar la acumulación y el tiempo de finalización. Conserva evidencias de tareas lentas con log_autovacuum_min_duration; utiliza pg_stat_io para aislar la I/O de los workers de autovacuum.
7. Ajustar gradualmente y revertir
Modifica una dimensión a la vez: aumenta slots o max workers, observa CPU, I/O, latencia y acumulación pendiente, y luego continúa. Si la contención aumenta, reduce la concurrencia, disminuye la frecuencia de una tabla o reprograma trabajos masivos. Registra la versión, el alcance de la tabla, la ventana de métricas y el valor de reversión para cada cambio, a fin de no confundir una acumulación temporal con una escasez permanente de capacidad.
Ejemplo de una respuesta sólida
Trato los slots de workers como el grupo de recursos, max workers como la concurrencia normal y los umbrales de tabla como el generador de trabajo. Las tablas activas reciben umbrales basados en el crecimiento de tuplas muertas; las tablas frías evitan escaneos innecesarios. Primero mido el efecto de la concurrencia de workers en la I/O y la latencia de consultas, y luego la incremento de forma gradual. La observabilidad combina fases de progreso, n_dead_tup, antigüedad de transacciones, registros de autovacuum y pg_stat_io. El wraparound tiene prioridad sobre la latencia ordinaria, y una transacción larga bloqueante se atiende antes de realizar el ajuste rutinario. Cada cambio cuenta con un registro de reversión.
Errores comunes
- Aumentar
autovacuum_max_workerssin agregar slots o sin verificar el grupo de workers compartidos. - Tratar los slots como concurrencia real a pesar de que se configuran en el inicio.
- Aplicar un único factor de escala a todas las tablas, retrasando las tablas pequeñas y escaneando en exceso las grandes.
- Usar
VACUUM FULLcomo mantenimiento rutinario a pesar de los bloqueos y del costo de reescritura de tabla. - Observar el espacio en disco ignorando la antigüedad de transacciones, las tuplas muertas y las fases de progreso.
- Deshabilitar autovacuum para reducir latencia olvidando la protección contra wraparound.
Preguntas de seguimiento y respuestas
¿Cuál es la diferencia entre autovacuum_worker_slots y autovacuum_max_workers?
El primero reserva slots de backend para workers en el inicio; el segundo limita los procesos de autovacuum que se ejecutan concurrentemente. Aumentar max workers por encima de los slots efectivos no genera esa concurrencia. PostgreSQL 18 permite cambios de max workers en tiempo de ejecución dentro del límite de slots.
¿Una mayor concurrencia hace que VACUUM sea más rápido?
No automáticamente. Puede acortar el tiempo de mantenimiento pero aumentar el uso de CPU, I/O y la contención de la aplicación. Debe evaluarse junto con el tiempo de finalización de la acumulación, la latencia de consultas y los picos de I/O.
¿Por qué usar factores de escala específicos por tabla?
Un porcentaje puede traducirse en una cantidad absoluta enorme de tuplas muertas en una tabla grande y en un disparador excesivamente disperso en una pequeña. Las configuraciones personalizadas por tabla alinean el trabajo con la tasa de actualización, el tamaño y el SLA.
¿Cómo demuestras que la I/O está ralentizando a los workers?
Utiliza las fases y el tiempo de retraso de pg_stat_progress_vacuum, correlaciona las filas de workers de autovacuum en pg_stat_io con la latencia de disco y las métricas de consultas de la aplicación, y compara la misma ventana de tiempo.
¿Cuándo debe tener prioridad el trabajo de wraparound?
Cuando la antigüedad de la transacción más antigua se acerca al umbral de protección, el progreso de freeze se queda atrás o el clúster ejecuta un autovacuum de prevención de wraparound, elimina los bloqueadores y completa el freeze primero. El ajuste comercial rutinario cede ante ese riesgo.