From cc20f04860dee68735672db983acb211590df633 Mon Sep 17 00:00:00 2001 From: Alexander Weaver Date: Mon, 1 Aug 2022 16:48:34 -0500 Subject: [PATCH] Alerting: Increase alert rule operation perf by replacing subquery with threshold calculation (#53069) * Replace subquery with threshold calculation * Use offset/limit to account for orgs with large gaps in IDs * Collapse into one statement * Drop dead constants * Revert to 2 query approach * Drop unused consts again --- pkg/services/ngalert/store/alertmanager.go | 47 +++++++++++++++------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/pkg/services/ngalert/store/alertmanager.go b/pkg/services/ngalert/store/alertmanager.go index 6f97df9fd59..d8580e6a6a7 100644 --- a/pkg/services/ngalert/store/alertmanager.go +++ b/pkg/services/ngalert/store/alertmanager.go @@ -22,7 +22,7 @@ var ( // ConfigRecordsLimit defines the limit of how many alertmanager configuration versions // should be stored in the database for each organization including the current one. // Has to be > 0 - ConfigRecordsLimit int64 = 100 + ConfigRecordsLimit int = 100 ) // GetLatestAlertmanagerConfiguration returns the lastest version of the alertmanager configuration. @@ -206,26 +206,43 @@ func getInsertQuery(driver string) string { } } -func (st *DBstore) deleteOldConfigurations(ctx context.Context, orgID, limit int64) (int64, error) { +func (st *DBstore) deleteOldConfigurations(ctx context.Context, orgID int64, limit int) (int64, error) { if limit < 1 { return 0, fmt.Errorf("failed to delete old configurations: limit is set to '%d' but needs to be > 0", limit) } - var affactedRows int64 + + if limit < 1 { + limit = ConfigRecordsLimit + } + + var affectedRows int64 err := st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + highest := &models.AlertConfiguration{} + ok, err := sess.Desc("id").Where("org_id = ?", orgID).OrderBy("id").Limit(1, limit-1).Get(highest) + if err != nil { + return err + } + if !ok { + // No configurations exist. Nothing to clean up. + affectedRows = 0 + return nil + } + + threshold := highest.ID - 1 + if threshold < 1 { + // Fewer than `limit` records even exist. Nothing to clean up. + affectedRows = 0 + return nil + } + res, err := sess.Exec(` DELETE FROM alert_configuration WHERE org_id = ? AND - id NOT IN ( - SELECT T.* FROM ( - SELECT id - FROM alert_configuration - WHERE org_id = ? ORDER BY id DESC LIMIT ? - )AS T - ) - `, orgID, orgID, limit) + id < ? + `, orgID, threshold) if err != nil { return err } @@ -233,11 +250,11 @@ func (st *DBstore) deleteOldConfigurations(ctx context.Context, orgID, limit int if err != nil { return err } - affactedRows = rows - if affactedRows > 0 { - st.Logger.Info("deleted old alert_configuration(s)", "org", orgID, "limit", limit, "delete_count", affactedRows) + affectedRows = rows + if affectedRows > 0 { + st.Logger.Info("deleted old alert_configuration(s)", "org", orgID, "limit", limit, "delete_count", affectedRows) } return nil }) - return affactedRows, err + return affectedRows, err }