VACUUM y ANALYZE son las dos operaciones de mantenimiento de bases de datos PostgreSQL más importantes.
Se utiliza un vacío para recuperar el espacio ocupado por "tuplas muertas" en una tabla. Se crea una tupla inactiva cuando se elimina o actualiza un registro (una eliminación seguida de una inserción). PostgreSQL no elimina físicamente la fila anterior de la tabla, sino que le coloca un "marcador" para que las consultas no devuelvan esa fila. Cuando se ejecuta un proceso de vacío, el espacio ocupado por estas tuplas muertas se marca como reutilizable por otras tuplas.
Una operación de "analizar" hace lo que dice su nombre:analiza el contenido de las tablas de una base de datos y recopila estadísticas sobre la distribución de valores en cada columna de cada tabla. El motor de consulta de PostgreSQL utiliza estas estadísticas para encontrar el mejor plan de consulta. A medida que se insertan, eliminan y actualizan filas en una base de datos, las estadísticas de las columnas también cambian. ANALIZAR, ya sea ejecutado manualmente por el DBA o automáticamente por PostgreSQL después de un vacío automático, asegura que las estadísticas estén actualizadas.
Aunque suenen relativamente sencillos, detrás de escena, pasar la aspiradora y analizar son dos procesos complejos. Afortunadamente, los DBA no tienen que preocuparse mucho por sus aspectos internos. Sin embargo, a menudo se confunden acerca de ejecutar estos procesos manualmente o establecer los valores óptimos para los parámetros de configuración.
En este artículo, compartiremos algunas de las mejores prácticas para VACUUM y ANALYZE.
Consejo 1:no ejecute VACUUM o ANALYZE manualmente sin motivo
El vaciado de PostgreSQL (vacío automático o manual) minimiza la acumulación de tablas y evita el ajuste de ID de transacción. Autovacuum no recupera el espacio en disco ocupado por las tuplas muertas. Sin embargo, ejecutar un VACUUM FULL el comando lo hará. Sin embargo, VACUUM FULL tiene su implicación en el rendimiento. La tabla de destino se bloquea exclusivamente durante la operación, evitando incluso lecturas en la tabla. El proceso también realiza una copia completa de la tabla, lo que requiere espacio adicional en el disco cuando se ejecuta. Recomendamos no ejecutar VACUUM FULL a menos que haya un porcentaje muy alto de hinchamiento y las consultas estén sufriendo mucho. También recomendamos utilizar los períodos de menor actividad de la base de datos.
También es una buena práctica no ejecutar aspiraciones manuales con demasiada frecuencia en toda la base de datos; la base de datos de destino ya podría haber sido aspirada de manera óptima por el proceso de vacío automático. Como resultado, es posible que un vacío manual no elimine las tuplas inactivas, pero cause cargas de E/S innecesarias o picos de CPU. Si es necesario, las aspiraciones manuales solo deben ejecutarse mesa por mesa cuando sea necesario, como proporciones bajas de filas vivas a filas muertas, o grandes espacios entre las aspiraciones automáticas. Además, las aspiraciones manuales deben ejecutarse cuando la actividad del usuario es mínima.
Autovacuum también mantiene actualizadas las estadísticas de distribución de datos de una tabla (no las reconstruye). Cuando se ejecuta manualmente, el ANALIZAR El comando en realidad reconstruye estas estadísticas en lugar de actualizarlas. Una vez más, reconstruir las estadísticas cuando ya están actualizadas de manera óptima mediante un autovacuum regular puede causar una presión innecesaria en los recursos del sistema.
El momento en que debe ejecutar ANALYZE manualmente es inmediatamente después de la carga masiva de datos en la tabla de destino. Una gran cantidad (incluso unos pocos cientos) de nuevas filas en una tabla existente sesgará significativamente la distribución de datos de su columna. Las nuevas filas harán que las estadísticas de las columnas existentes queden desactualizadas. Cuando el optimizador de consultas utiliza dichas estadísticas, el rendimiento de las consultas puede ser muy lento. En estos casos, ejecutar el comando ANALIZAR inmediatamente después de una carga de datos para reconstruir completamente las estadísticas es una mejor opción que esperar a que se active el vacío automático.
Consejo 2:ajuste fino del umbral de vacío automático
Es fundamental comprobar o ajustar el autovacuum y analizar los parámetros de configuración en el postgresql.conf archivo o en propiedades de tablas individuales para lograr un equilibrio entre el vacío automático y la mejora del rendimiento.
PostgreSQL utiliza dos parámetros de configuración para decidir cuándo iniciar un vacío automático:
- autovacuum_vacuum_threshold :esto tiene un valor predeterminado de 50
- autovacuum_vacuum_scale_factor :esto tiene un valor predeterminado de 0.2
Juntos, estos parámetros le indican a PostgreSQL que inicie un vacío automático cuando la cantidad de filas muertas en una tabla excede la cantidad de filas en esa tabla multiplicada por el factor de escala, más el umbral de vacío. En otras palabras, PostgreSQL iniciará el autovacío en una tabla cuando:
pg_stat_user_tables.n_dead_tup > (pg_class.reltuples x autovacuum_vacuum_scale_factor) + autovacuum_vacuum_threshold
Para mesas de tamaño pequeño a mediano, esto puede ser suficiente. Por ejemplo, una tabla con 10 000 filas, el número de filas muertas debe ser superior a 2050 ((10 000 x 0,2) + 50) antes de que se inicie un vacío automático.
No todas las tablas de una base de datos experimentan la misma tasa de modificación de datos. Por lo general, algunas tablas grandes experimentarán modificaciones de datos frecuentes y, como resultado, tendrán una mayor cantidad de filas muertas. Es posible que los valores predeterminados no funcionen para dichas tablas. Por ejemplo, con los valores predeterminados, una tabla con 1 millón de filas necesitará tener más de 200 050 filas muertas antes de que comience un vacío automático ((1000 000 x 0,2) + 50). Esto puede significar intervalos más prolongados entre autovacíos, tiempos de autovacío cada vez más prolongados y, lo que es peor, que el autovacío no se ejecute en absoluto si las transacciones activas en la mesa lo están bloqueando.
Por lo tanto, el objetivo debe ser establecer estos umbrales en valores óptimos para que el autovacío pueda ocurrir a intervalos regulares y no tome mucho tiempo (y afecte las sesiones de los usuarios) mientras mantiene la cantidad de filas muertas relativamente baja.
Un enfoque es utilizar uno u otro parámetro. Por lo tanto, si establecemos autovacuum_vacuum_scale_factor en 0 y, en su lugar, establecemos autovacuum_vacuum_threshold en, por ejemplo, 5000, una tabla se vaciará automáticamente cuando el número de filas muertas sea superior a 5000.
Sugerencia 3:Ajuste el umbral de análisis automático
Similar a autovacuum, autoanalyze también usa dos parámetros que deciden cuándo autovacuum también activará un autoanálisis:
- autovacuum_analyze_threshold :esto tiene un valor predeterminado de 50
- autovacuum_analyze_scale_factor :esto tiene un valor predeterminado de 0.1
Al igual que autovacuum, el parámetro autovacuum_analyze_threshold se puede establecer en un valor que dicte el número de tuplas insertadas, eliminadas o actualizadas en una tabla antes de que comience un análisis automático. Recomendamos configurar este parámetro por separado en tablas grandes y con muchas transacciones. La configuración de la tabla anulará los valores de postgresql.conf.
El fragmento de código a continuación muestra la sintaxis SQL para modificar la configuración de autovacuum_analyze_threshold para una tabla.
ALTER TABLE <table_name> SET (autovacuum_analyze_threshold = <threshold rows>)
Consejo 4:Perfeccione los trabajadores de vacío automático
Otro parámetro que los DBA suelen pasar por alto es autovacuum_max_workers , que tiene un valor predeterminado de 3. Autovacuum no es un proceso único, sino varios subprocesos de vacío individuales que se ejecutan en paralelo. El motivo para especificar varios trabajadores es garantizar que la limpieza de tablas grandes no retrase la limpieza de tablas y sesiones de usuario más pequeñas. El parámetro autovacuum_max_workers le dice a PostgreSQL que aumente la cantidad de subprocesos de trabajo de autovacuum para realizar la limpieza.
Una práctica común de los administradores de bases de datos de PostgreSQL es aumentar la cantidad máxima de subprocesos de trabajo con la esperanza de acelerar el vacío automático. Esto no funciona ya que todos los subprocesos comparten el mismo autovacuum_vacuum_cost_limit , que tiene un valor predeterminado de 200. A cada subproceso de vacío automático se le asigna un límite de costo utilizando esta fórmula que se muestra a continuación:
individual thread’s cost_limit = autovacuum_vacuum_cost_limit / autovacuum_max_workers
El costo del trabajo realizado por un subproceso de vacío automático se calcula utilizando tres parámetros:
- vacuum_cost_page_hit :esto tiene un valor predeterminado de 1
- vacuum_cost_page_miss :esto tiene un valor predeterminado de 10
- vacuum_cost_page_dirty :tiene un valor predeterminado de 20
Lo que significan estos parámetros es esto:
- Cuando un subproceso de vacío encuentra la página de datos que se supone que debe limpiar en el búfer compartido, el costo es 1.
- Si la página de datos no está en el búfer compartido, sino en la memoria caché del sistema operativo, el costo será de 10.
- Si la página debe marcarse como sucia porque el subproceso de vacío tuvo que eliminar filas muertas, el costo será de 20.
Un mayor número de subprocesos de trabajo reducirá el límite de costo para cada subproceso. Como a cada subproceso se le asigna un límite de costo más bajo, se dormirá con mayor frecuencia a medida que se alcanza fácilmente el umbral de costo, lo que en última instancia hace que todo el proceso de vacío funcione lentamente. Recomendamos aumentar autovacuum_vacuum_cost_limit a un valor más alto, como 2000, y luego ajustar la cantidad máxima de subprocesos de trabajo.
Una mejor manera es ajustar estos parámetros para tablas individuales solo cuando sea necesario. Por ejemplo, si el vacío automático de una tabla transaccional grande tarda demasiado, la tabla puede configurarse temporalmente para usar su propio límite de costo de vacío y demoras de costos. El límite de costo y la demora anularán los valores de todo el sistema establecidos en postgresql.conf.
El fragmento de código siguiente muestra cómo configurar tablas individuales.
ALTER TABLE <table_name> SET (autovacuum_vacuum_cost_limit = <large_value>) ALTER TABLE <table_name> SET (autovacuum_vacuum_cost_delay = <lower_cost_delay>)
El uso del primer parámetro garantizará que el subproceso de vacío automático asignado a la tabla realice más trabajo antes de irse a dormir. Reducir el autovacuum_vacuum_cost_delay también significará que el subproceso está durmiendo menos cantidad de tiempo.
Reflexiones finales
Como puede ver, cambiar los parámetros de configuración para el vacío y el análisis es sencillo, pero primero necesita una observación cuidadosa. Cada base de datos es diferente en cuanto a su tamaño, patrón de tráfico y tasa de transacciones. Recomendamos que los administradores de bases de datos comiencen recopilando suficiente información sobre su base de datos antes de cambiar los parámetros o implementar un régimen manual de vacío/análisis. Dicha información podría ser:
- Número de filas en cada tabla
- Número de tuplas muertas en cada tabla
- La hora del último vacío de cada mesa
- La hora del último análisis de cada tabla
- La tasa de inserción/actualización/eliminación de datos en cada tabla
- El tiempo que tarda el autovacío en cada mesa
- Advertencias sobre mesas que no se aspiran
- Rendimiento actual de las consultas más críticas y las tablas a las que acceden
- Rendimiento de las mismas consultas después de un vacío/análisis manual
Desde aquí, los DBA pueden seleccionar algunas tablas "piloto" para comenzar a optimizar. Pueden empezar a cambiar las propiedades de vacío/análisis de las tablas y comprobar el rendimiento. PostgreSQL es un motor de base de datos inteligente:los DBA a menudo encontrarán que probablemente sea mejor dejar que PostgreSQL haga la limpieza y el análisis en lugar de hacerlo manualmente.