osbuild-service-maintenance: Vacuum tables

Call vacuum analyze after each chunk of updates, and dump vacuum stats
at the beginning and end of the db cleanup.

Nulling results can increase size on disk, but calling vacuum analyze
will free up space within the table (not on disk) and reuse the space
for new inserts and updates.
This commit is contained in:
Sanne Raymaekers 2022-06-07 13:12:14 +02:00 committed by Ondřej Budai
parent 8bfc6c9961
commit ff408aa68f
2 changed files with 89 additions and 0 deletions

View file

@ -22,6 +22,11 @@ func DBCleanup(dbURL string, dryRun bool, cutoff time.Time) error {
return fmt.Errorf("Error querying jobs: %v", err)
}
err = jobs.LogVacuumStats()
if err != nil {
logrus.Errorf("Error running vacuum stats: %v", err)
}
for k, v := range jobsByType {
logrus.Infof("Deleting results from %d %s jobs", len(v), k)
if dryRun {
@ -42,8 +47,17 @@ func DBCleanup(dbURL string, dryRun bool, cutoff time.Time) error {
continue
}
logrus.Infof("Deleted results from %d jobs out of %d job ids", rows, len(v))
err = jobs.VacuumAnalyze()
if err != nil {
logrus.Errorf("Error running vacuum analyze: %v", err)
}
}
}
err = jobs.LogVacuumStats()
if err != nil {
logrus.Errorf("Error running vacuum stats: %v", err)
}
return nil
}

View file

@ -110,6 +110,14 @@ const (
UPDATE jobs
SET result = NULL
WHERE id = ANY($1)`
sqlVacuumAnalyze = `
VACUUM ANALYZE`
sqlVacuumStats = `
SELECT relname, pg_size_pretty(pg_total_relation_size(relid)),
n_tup_ins, n_tup_upd, n_tup_del, n_live_tup, n_dead_tup,
vacuum_count, autovacuum_count, analyze_count, autoanalyze_count,
last_vacuum, last_autovacuum, last_analyze, last_autoanalyze
FROM pg_stat_user_tables`
)
type DBJobQueue struct {
@ -658,3 +666,70 @@ func (q *DBJobQueue) DeleteJobResult(jobIds []uuid.UUID) (int64, error) {
}
return tag.RowsAffected(), nil
}
func (q *DBJobQueue) VacuumAnalyze() error {
conn, err := q.pool.Acquire(context.Background())
if err != nil {
return fmt.Errorf("error connecting to database: %v", err)
}
defer conn.Release()
_, err = conn.Exec(context.Background(), sqlVacuumAnalyze)
if err != nil {
return fmt.Errorf("Error running VACUUM ANALYZE: %v", err)
}
return nil
}
func (q *DBJobQueue) LogVacuumStats() error {
conn, err := q.pool.Acquire(context.Background())
if err != nil {
return fmt.Errorf("error connecting to database: %v", err)
}
defer conn.Release()
rows, err := conn.Query(context.Background(), sqlVacuumStats)
if err != nil {
return fmt.Errorf("Error querying vacuum stats: %v", err)
}
defer rows.Close()
for rows.Next() {
var relName, relSize string
var ins, upd, del, live, dead, vc, avc, ac, aac int64
var lvc, lavc, lan, laan *time.Time
err = rows.Scan(&relName, &relSize, &ins, &upd, &del, &live, &dead,
&vc, &avc, &ac, &aac,
&lvc, &lavc, &lan, &laan)
if err != nil {
return err
}
logrus.Infof("Stats for table %s", relName)
logrus.Infof(" Total table size: %s", relSize)
logrus.Info(" Tuples:")
logrus.Infof(" Inserted: %d", ins)
logrus.Infof(" Updated: %d", upd)
logrus.Infof(" Deleted: %d", del)
logrus.Infof(" Live: %d", live)
logrus.Infof(" Dead: %d", dead)
logrus.Info(" Vacuum stats:")
logrus.Infof(" Vacuum count: %d", vc)
logrus.Infof(" AutoVacuum count: %d", avc)
logrus.Infof(" Last vacuum: %v", lvc)
logrus.Infof(" Last autovacuum: %v", lavc)
logrus.Info(" Analyze stats:")
logrus.Infof(" Analyze count: %d", ac)
logrus.Infof(" AutoAnalyze count: %d", aac)
logrus.Infof(" Last analyze: %v", lan)
logrus.Infof(" Last autoanalyze: %v", laan)
logrus.Info("---")
}
if rows.Err() != nil {
return rows.Err()
}
return nil
}