From 095020b1ca515b3454644ff7a8f7e4ccdc8742e2 Mon Sep 17 00:00:00 2001
From: root <qiuwenhuifx@gmail.com>
Date: Thu, 28 Nov 2024 13:46:00 +0800
Subject: [PATCH] Add guc to optimize the autovacuum tigger algorithm

---
 src/backend/postmaster/autovacuum.c           | 23 +++++++++++++++++++----
 src/backend/utils/misc/guc_tables.c           | 17 +++++++++++++++++
 src/backend/utils/misc/postgresql.conf.sample |  1 +
 src/include/postmaster/autovacuum.h           | 10 ++++++++++
 4 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index dc3cf87..224e3bb 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
@@ -132,6 +132,7 @@ 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,10 +3039,24 @@ 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_LINEAR:
+				vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples;
+				anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples;
+				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, vac_base_thresh + anl_scale_factor * sqrt(reltuples) * 1000.0 );
+				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, vac_base_thresh + anl_scale_factor * pow(reltuples,0.7) * 100.0 );
+				break;
+			default:
+				elog(ERROR, "Unknown vacuum_algorithm value.");
+		}
 		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
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 9845abd..1098984 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -474,6 +474,13 @@ static const struct config_enum_entry wal_compression_options[] = {
 	{NULL, 0, false}
 };
 
+/* vacuum_algorithm guc */
+static const struct config_enum_entry autovacuum_algorithm_options[] = {
+	{"linear", AUTOVACUUM_ALGORITHM_LINEAR, false},
+	{"sqrt", AUTOVACUUM_ALGORITHM_SQRT, false},
+	{"pow", AUTOVACUUM_ALGORITHM_POW, false},
+	{NULL, 0, false}
+};
 /*
  * Options for enum values stored in other modules
  */
@@ -5217,6 +5224,16 @@ struct config_enum ConfigureNamesEnum[] =
 		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 407cd1e..95fd2e6 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -161,6 +161,7 @@
 #vacuum_buffer_usage_limit = 2MB	# size of vacuum and analyze buffer access strategy ring;
 					# 0 to disable vacuum buffer access strategy;
 					# range 128kB to 16GB
+#autovacuum_algorithm = linear # autovacuum_algorithm of (sqrt,linear,pow) default linear
 
 # SLRU buffers (change requires restart)
 #commit_timestamp_buffers = 0		# memory for pg_commit_ts (0 = auto)
diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h
index cae1e8b..f8513e2 100644
--- a/src/include/postmaster/autovacuum.h
+++ b/src/include/postmaster/autovacuum.h
@@ -47,6 +47,16 @@ extern PGDLLIMPORT int AutovacuumLauncherPid;
 
 extern PGDLLIMPORT int Log_autovacuum_min_duration;
 
+/*  algorithms for Vacuum */
+typedef enum Autovacuum_algorithm
+{
+	AUTOVACUUM_ALGORITHM_LINEAR,
+	AUTOVACUUM_ALGORITHM_SQRT,
+	AUTOVACUUM_ALGORITHM_POW
+} Autovacuum_algorithm;
+
+extern PGDLLIMPORT int autovacuum_algorithm;
+
 /* Status inquiry functions */
 extern bool AutoVacuumingActive(void);
 
-- 
1.8.3.1

