Primeiramente devo agradecer ao Fabrízio Mello(http://fabriziomello.blogspot.com.br/) que trabalhou junto comigo na rotina abaixo.
CENÁRIO: Base 24x7 em uma base de quase 500GB.
PROBLEMA: Optou-se por tornar o auto-vacuum mais agressivo para não impactar no ambiente durante o horário comercial, mas o VACUUM na base inteira ainda que executado no domingo demorava muito, mesmo com alteração dos parâmetros de memória.
SOLUÇÃO: Em conjunto com o Fabrízio Mello, o qual tem minha indicação incondicional, elaboramos a rotina abaixo através do PgAgent em um job de BATCH:
#!/bin/bash PGUSER="postgres" PGPORT="5432" PGDATABASE="postgres" PGHOST="localhost" export PGUSER PGPORT PGDATABASE PGHOST START="00:00:00" END="06:00:00" LIMIT="20" SQL=" SELECT 'VACUUM ANALYZE VERBOSE '||quote_ident(schemaname)||'.'||quote_ident(relname)||';' FROM pg_stat_user_tables WHERE (n_dead_tup+n_live_tup)>0 ORDER BY (n_dead_tup * 100)/(n_dead_tup+n_live_tup) desc LIMIT ${LIMIT};" echo "Iniciando rotina de vacuum:" > /tmp/vacuum-maintenance-$PGDATABASE-v2.log psql -Atq -c "$SQL" | while read i do now=$(date +%H%M%S) if [[ "$now" == "$START" || "$now" > "$START" && "$now" < "$END" || "$now" == "$END" ]] then psql -c "$i" >> /tmp/vacuum-maintenance-$PGDATABASE-v2.log 2>&1 fi done
Em resumo o job realiza VACUUM ANALYZE nas 20(quantidade definida com o parâmetro LIMIT) tabelas que mais tem tupulas mortas. Entretanto a execução ocorre apenas entre o START e o END que for definido no job, caso finalize a tabela 19 e o horário for maior que o definido em END o job é finalizado sem realizar o VACUUM ANALYZE na tabela 20 da query. O resultado podes ver em /tmp/vacuum-maintenance-$PGDATABASE-v2.log onde $PGDATABASE é o nome da base alvo do BATCH.