¿Cuánto tiempo llevará una operación de vacío / autovacío?

18

Administro una gran base de datos (algunos cientos de conciertos) que contiene tablas con varios roles, algunos de ellos con millones de registros. Algunas tablas solo reciben una gran cantidad de inserciones y eliminaciones, algunas otras pocas inserciones y una gran cantidad de actualizaciones.

La base de datos se ejecuta en PostgreSQL 8.4 en un sistema Debian 6.0 amd64 con 16 gigabytes de RAM.

La pregunta es a veces el proceso de autovacío en una tabla, lleva mucho tiempo (días) en completarse. Quiero poder decir aproximadamente cuánto tiempo llevará un comando de vacío en particular, para poder decidir si cancelarlo o no. Además, si hubiera un indicador de progreso para las operaciones de vacío de Postgres, sería realmente útil.

Editar:

No estoy buscando una solución a prueba de balas. Solo una pista aproximada sobre el número de tuplas muertas o los bytes de E / S necesarios es suficiente para decidir. Es realmente molesto no tener idea de cuándo VACUUMterminará, en absoluto.

He visto que pg_catalog.pg_stat_all_tablestiene una columna para la cantidad de tuplas muertas. Por lo tanto, es posible tener una estimación, incluso si eso significa que uno tiene que ir a ANALYZEla mesa antes. Por otro lado, autovacuum_vacuum_thresholdy la autovacuum_vacuum_scale_factorconfiguración por sí sola demuestra que el propio postgres sabe algo sobre la cantidad de cambio en las tablas y probablemente también lo pone en manos del DBA.

No estoy seguro de qué consulta ejecutar, porque cuando ejecuto VACUUM VERBOSE, veo que no solo se procesan las tablas, sino también los índices.

zaadeh
fuente

Respuestas:

34

En mi PostgreSQL (8.3) uso este truco:

  1. Obtengo el tamaño de disco de la tabla usando pg_total_relation_size(): esto incluye índices y el tamaño de TOAST, que es lo que VACUUMprocesa. Esto me da la idea de cuántos bytes VACUUMtiene que leer.
  2. Corro VACUUMsobre la mesa.
  3. Encuentro el piddel VACUUMproceso (en pg_catalog.pg_stat_activity).
  4. En el shell de Linux ejecuto while true; do cat /proc/123/io | grep read_bytes; sleep 60; done(donde 123está el pid), esto me muestra los bytes leídos por el proceso desde el disco hasta ahora.

Esto me da una idea aproximada de cuántos bytes procesa (lee) cada minuto el VACUUM. Supongo que VACUUMdebe leer toda la tabla (incluidos los índices y TOAST), cuyo tamaño de disco sé del paso 1.

Supongo que la tabla es lo suficientemente grande como para que la mayoría de sus páginas deben leerse desde el disco (no están presentes en la memoria compartida de Postgres), por lo que el read_bytescampo es lo suficientemente bueno como para ser utilizado como un contador de progreso.

Cada vez que hice esto, el total de bytes leídos por el proceso no fue más del 5% del tamaño total de la relación, por lo que supongo que este enfoque puede ser lo suficientemente bueno para usted.

Roman Hocke
fuente
Nasty :) ¿Funciona esto también para versiones posteriores? Y, lo que es más importante, ¿para autovacuum?
dezso
No lo he probado para versiones más nuevas. Debería funcionar VACUUM FULLen 9.0+, ya que reescribe completamente la tabla. También debería funcionar para regular VACUUM, pero aún no lo he probado. Porque autovacuumfuncionaría si pudieras atrapar el proceso de trabajo de vacío automático en una tabla determinada, pero no sé cómo lograrlo.
Roman Hocke
¿Tiene alguna sugerencia sobre cómo lograr esto con RDS? Naturalmente, no tenemos acceso a un shell de Linux cuando utilizamos RDS, pero también nos gustaría poder estimar esto.
jwg2s
@ jwg2s ¿Qué quiere decir con "RDS", por favor? Servicios de bases de datos de Amazon? Si es así, desafortunadamente no estoy familiarizado con él :-( Quizás su apoyo ayudaría.
Roman Hocke
1
Parece funcionar bien en PG 10 con vacío lleno también.
DylanYoung
9

Esto es muy difícil de determinar. Puede sintonizar autovacuum para ser más agresivo o más suave. Pero cuando se configura en leve y se está quedando atrás y la carga de E / S de base es demasiado alta, puede suceder que nunca alcance un estado de vacío adecuado; entonces verá que el proceso se ejecuta y se ejecuta y se ejecuta. Además, las ediciones posteriores de PostreSQL han mejorado mucho las capacidades de vacío automático, esto solo puede ser suficiente para pasar a una de ellas (preferiblemente 9.2 como la más reciente).

La barra de progreso parece una buena idea, pero imagino que no es tan fácil de implementar de manera significativa. Como tiene una carga constante en sus mesas, es muy posible que el progreso aparentemente esté retrocediendo (quiero decir que el recuento de filas muertas / porcentaje aumenta en lugar de disminuir), entonces, ¿qué conclusión saca?

dezso
fuente
2
Prefiero ver algún tipo de indicador de progreso, incluso si va hacia atrás, en lugar de nada.
zaadeh
3
VACUUM ANALYZE VERBOSEal menos imprime alguna actividad en la consola, ya que lo hace es cosa. Es mejor que simplemente mirar un mensaje estático preguntándose si algo está atascado durante horas.
Nombre falso el
La pregunta se refiere a "vacío / autovacío". Lo anterior solo es útil VACUUM, no para autovacuum, pero sigue siendo algo.
Nombre falso el
@FakeName Eh, leí mal la pregunta, me perdí la parte de vacío manual. Lo siento, estoy borrando mi comentario.
dezso
3

En nuestra producción, una de las tablas más grandes tenía este registro:

pages: 0 removed, 1801722 remain
tuples: 238912 removed, 42582083 remain, 1396 are dead but not yet removable
buffer usage: 9477565 hits, 3834218 misses, 2220101 dirtied
avg read rate: 2.976 MB/s, avg write rate: 1.723 MB/s
system usage: CPU 68.47s/177.49u sec elapsed 10065.08 sec

Este es, con mucho, el peor consumo de recursos, todas las otras tablas han tomado menos de 2 s.

Para ver estos tipos de registros, debe ejecutar esto:

alter system set log_autovacuum_min_duration TO 5; 

(durante 5 ms), vuelva a cargar el archivo de configuración.

Stonelazy
fuente
3

Encontré útil esta publicación y esta publicación , pero como otros han mencionado, puede ser difícil calcular el progreso general del vacío, ya que el proceso involucra algunas operaciones separadas.

Utilizo esta consulta para monitorear el progreso del escaneo de la tabla de vacío, que parece ser la mayor parte del trabajo:

SELECT heap_blks_scanned/cast(heap_blks_total as numeric)*100 as heap_blks_percent, progress.*, activity.query
FROM pg_stat_progress_vacuum AS progress
INNER JOIN pg_stat_activity AS activity ON activity.pid = progress.pid;

Sin embargo, esto no incluirá el escaneo de índice, que ocurre después, y puede tomar el mismo tiempo, si no más, si tiene una tonelada de índices. Desafortunadamente, no puedo encontrar ninguna manera de monitorear el escaneo / aspiración de índices.

Cerin
fuente