From fe09de086939c44de62fbc20acfd874c4389ba16 Mon Sep 17 00:00:00 2001
From: root <qiuwenhuifx@gmail.com>
Date: Mon, 18 Nov 2024 14:44:38 +0800
Subject: [PATCH] Add guc to optimize the autovacuum tigger algorithm

---
 src/backend/postmaster/autovacuum.c           | 34 ++++++++++++++++++++++-----
 src/backend/utils/misc/guc_tables.c           | 18 +++++++++++++-
 src/backend/utils/misc/postgresql.conf.sample |  2 +-
 src/include/postmaster/autovacuum.h           | 11 +++++++++
 4 files changed, 57 insertions(+), 8 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index dc3cf87..ab4020e 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -109,7 +109,7 @@
 #include "utils/syscache.h"
 #include "utils/timeout.h"
 #include "utils/timestamp.h"
-
+#include <math.h>
 
 /*
  * GUC parameters
@@ -131,7 +131,7 @@ double		autovacuum_vac_cost_delay;
 int			autovacuum_vac_cost_limit;
 
 int			Log_autovacuum_min_duration = 600000;
-
+int         autovacuum_algorithm = AUTOVACUUM_ALGORITHM_LINEAR;
 /* the minimum allowed time between two awakenings of the launcher */
 #define MIN_AUTOVAC_SLEEPTIME 100.0 /* milliseconds */
 #define MAX_AUTOVAC_SLEEPTIME 300	/* seconds */
@@ -3038,11 +3038,33 @@ relation_needs_vacanalyze(Oid relid,
 		/* If the table hasn't yet been vacuumed, take reltuples as zero */
 		if (reltuples < 0)
 			reltuples = 0;
-
-		vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples;
+		switch (autovacuum_algorithm)
+		{
+			case AUTOVACUUM_ALGORITHM_LOG2:
+				vacthresh = (float4) fmin(vac_base_thresh + (vac_scale_factor * reltuples), vac_base_thresh + vac_scale_factor * log2(reltuples) * 100000.0 );
+				anlthresh = (float4) fmin(anl_base_thresh + (anl_scale_factor * reltuples), anl_base_thresh + anl_scale_factor * log2(reltuples) * 100000.0 );
+				elog(DEBUG2, "Using log2 algorithm for vacuum, vacthresh values is %f,anlthresh values is %f" ,vacthresh, anlthresh );
+				break;
+			case AUTOVACUUM_ALGORITHM_SQRT:
+				vacthresh = (float4) fmin(vac_base_thresh + (vac_scale_factor * reltuples), vac_base_thresh + vac_scale_factor * sqrt(reltuples) * 1000.0 );
+				anlthresh = (float4) fmin(anl_base_thresh + (anl_scale_factor * reltuples), anl_base_thresh + anl_scale_factor * sqrt(reltuples) * 1000.0 );
+				elog(DEBUG2, "Using sqrt algorithm for vacuum, vacthresh values is %f,anlthresh values is %f" , vacthresh, anlthresh );
+				break;
+			case AUTOVACUUM_ALGORITHM_LINEAR:
+				vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples;
+				anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples;
+				elog(DEBUG2, "Using linear algorithm for vacuum, vacthresh values is %f,anlthresh values is %f", vacthresh, anlthresh );
+				break;
+			case AUTOVACUUM_ALGORITHM_POW:
+				vacthresh = (float4) fmin(vac_base_thresh + (vac_scale_factor * reltuples), vac_base_thresh + vac_scale_factor * pow(reltuples, 0.7) * 100.0 );
+				anlthresh = (float4) fmin(anl_base_thresh + (anl_scale_factor * reltuples), anl_base_thresh + anl_scale_factor * pow(reltuples, 0.7) * 100.0 );
+				elog(DEBUG2, "Using pow algorithm for vacuum, vacthresh values is %f,anlthresh values is %f", vacthresh, anlthresh);
+				break;
+			default:
+				elog(ERROR, "Unknown vacuum_algorithm value.");
+				break;
+		}
 		vacinsthresh = (float4) vac_ins_base_thresh + vac_ins_scale_factor * reltuples;
-		anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples;
-
 		/*
 		 * Note that we don't need to take special consideration for stat
 		 * reset, because if that happens, the last vacuum and analyze counts
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 8a67f01..5ef9304 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -474,6 +474,14 @@ static const struct config_enum_entry wal_compression_options[] = {
 	{NULL, 0, false}
 };
 
+/* vacuum_algorithm guc */
+static const struct config_enum_entry autovacuum_algorithm_options[] = {
+	{"log2", AUTOVACUUM_ALGORITHM_LOG2, false},
+	{"sqrt", AUTOVACUUM_ALGORITHM_SQRT, false},
+	{"linear", AUTOVACUUM_ALGORITHM_LINEAR, false},
+	{"pow", AUTOVACUUM_ALGORITHM_POW, false},
+	{NULL, 0, false}
+};
 /*
  * Options for enum values stored in other modules
  */
@@ -5206,7 +5214,15 @@ struct config_enum ConfigureNamesEnum[] =
 		DEBUG_LOGICAL_REP_STREAMING_BUFFERED, debug_logical_replication_streaming_options,
 		NULL, NULL, NULL
 	},
-
+	{
+		{"autovacuum_algorithm", PGC_SIGHUP, AUTOVACUUM,
+		gettext_noop("vacuum trigger algorithm."),
+		NULL
+		},
+		&autovacuum_algorithm,
+		AUTOVACUUM_ALGORITHM_LINEAR, autovacuum_algorithm_options,
+		NULL, NULL, NULL
+	},
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 39a3ac2..4c29fe9 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -684,7 +684,7 @@
 #autovacuum_vacuum_cost_limit = -1	# default vacuum cost limit for
 					# autovacuum, -1 means use
 					# vacuum_cost_limit
-
+#autovacuum_algorithm = linear          # autovacuum_algorithm (log2,sqrt,linear,pow) default linear 
 
 #------------------------------------------------------------------------------
 # CLIENT CONNECTION DEFAULTS
diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h
index cae1e8b..6fe6732 100644
--- a/src/include/postmaster/autovacuum.h
+++ b/src/include/postmaster/autovacuum.h
@@ -47,6 +47,17 @@ extern PGDLLIMPORT int AutovacuumLauncherPid;
 
 extern PGDLLIMPORT int Log_autovacuum_min_duration;
 
+/*  algorithms for Vacuum */
+typedef enum Autovacuum_algorithm
+{
+   AUTOVACUUM_ALGORITHM_LOG2,
+   AUTOVACUUM_ALGORITHM_SQRT,
+   AUTOVACUUM_ALGORITHM_LINEAR,
+   AUTOVACUUM_ALGORITHM_POW
+} Autovacuum_algorithm;
+ 
+extern PGDLLIMPORT int autovacuum_algorithm;
+
 /* Status inquiry functions */
 extern bool AutoVacuumingActive(void);
 
-- 
1.8.3.1

