From ff408aa68f25181e817d38b20172eff28c8b5866 Mon Sep 17 00:00:00 2001 From: Sanne Raymaekers Date: Tue, 7 Jun 2022 13:12:14 +0200 Subject: [PATCH] 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. --- cmd/osbuild-service-maintenance/db.go | 14 ++++ internal/jobqueue/dbjobqueue/dbjobqueue.go | 75 ++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/cmd/osbuild-service-maintenance/db.go b/cmd/osbuild-service-maintenance/db.go index 8943b7bb4..5a56e05fb 100644 --- a/cmd/osbuild-service-maintenance/db.go +++ b/cmd/osbuild-service-maintenance/db.go @@ -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 } diff --git a/internal/jobqueue/dbjobqueue/dbjobqueue.go b/internal/jobqueue/dbjobqueue/dbjobqueue.go index 81e9ed6c2..e3059dc25 100644 --- a/internal/jobqueue/dbjobqueue/dbjobqueue.go +++ b/internal/jobqueue/dbjobqueue/dbjobqueue.go @@ -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 + +}