@@ -35,6 +35,8 @@ typedef struct vacuumingOptions
3535 bool skip_locked ;
3636 int min_xid_age ;
3737 int min_mxid_age ;
38+ int parallel_workers ; /* >= 0 indicates user specified the
39+ * parallel degree, otherwise -1 */
3840} vacuumingOptions ;
3941
4042
@@ -87,6 +89,7 @@ main(int argc, char *argv[])
8789 {"full" , no_argument , NULL , 'f' },
8890 {"verbose" , no_argument , NULL , 'v' },
8991 {"jobs" , required_argument , NULL , 'j' },
92+ {"parallel" , required_argument , NULL , 'P' },
9093 {"maintenance-db" , required_argument , NULL , 2 },
9194 {"analyze-in-stages" , no_argument , NULL , 3 },
9295 {"disable-page-skipping" , no_argument , NULL , 4 },
@@ -116,14 +119,15 @@ main(int argc, char *argv[])
116119
117120 /* initialize options to all false */
118121 memset (& vacopts , 0 , sizeof (vacopts ));
122+ vacopts .parallel_workers = -1 ;
119123
120124 pg_logging_init (argv [0 ]);
121125 progname = get_progname (argv [0 ]);
122126 set_pglocale_pgservice (argv [0 ], PG_TEXTDOMAIN ("pgscripts" ));
123127
124128 handle_help_version_opts (argc , argv , "vacuumdb" , help );
125129
126- while ((c = getopt_long (argc , argv , "h:p:U:wWeqd:zZFat:fvj:" , long_options , & optindex )) != -1 )
130+ while ((c = getopt_long (argc , argv , "h:p:U:wWeqd:zZFat:fvj:P: " , long_options , & optindex )) != -1 )
127131 {
128132 switch (c )
129133 {
@@ -183,6 +187,14 @@ main(int argc, char *argv[])
183187 exit (1 );
184188 }
185189 break ;
190+ case 'P' :
191+ vacopts .parallel_workers = atoi (optarg );
192+ if (vacopts .parallel_workers < 0 )
193+ {
194+ pg_log_error ("parallel vacuum degree must be a non-negative integer" );
195+ exit (1 );
196+ }
197+ break ;
186198 case 2 :
187199 maintenance_db = pg_strdup (optarg );
188200 break ;
@@ -258,6 +270,23 @@ main(int argc, char *argv[])
258270 /* allow 'and_analyze' with 'analyze_only' */
259271 }
260272
273+ /* Prohibit full and analyze_only options with parallel option */
274+ if (vacopts .parallel_workers >= 0 )
275+ {
276+ if (vacopts .analyze_only )
277+ {
278+ pg_log_error ("cannot use the \"%s\" option when performing only analyze" ,
279+ "parallel" );
280+ exit (1 );
281+ }
282+ if (vacopts .full )
283+ {
284+ pg_log_error ("cannot use the \"%s\" option when performing full" ,
285+ "parallel" );
286+ exit (1 );
287+ }
288+ }
289+
261290 setup_cancel_handler (NULL );
262291
263292 /* Avoid opening extra connections. */
@@ -405,6 +434,13 @@ vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
405434 exit (1 );
406435 }
407436
437+ if (vacopts -> parallel_workers >= 0 && PQserverVersion (conn ) < 130000 )
438+ {
439+ pg_log_error ("cannot use the \"%s\" option on server versions older than PostgreSQL %s" ,
440+ "--parallel" , "13" );
441+ exit (1 );
442+ }
443+
408444 if (!quiet )
409445 {
410446 if (stage != ANALYZE_NO_STAGE )
@@ -823,6 +859,14 @@ prepare_vacuum_command(PQExpBuffer sql, int serverVersion,
823859 appendPQExpBuffer (sql , "%sANALYZE" , sep );
824860 sep = comma ;
825861 }
862+ if (vacopts -> parallel_workers >= 0 )
863+ {
864+ /* PARALLEL is supported since v13 */
865+ Assert (serverVersion >= 130000 );
866+ appendPQExpBuffer (sql , "%sPARALLEL %d" , sep ,
867+ vacopts -> parallel_workers );
868+ sep = comma ;
869+ }
826870 if (sep != paren )
827871 appendPQExpBufferChar (sql , ')' );
828872 }
@@ -886,6 +930,7 @@ help(const char *progname)
886930 printf (_ (" -j, --jobs=NUM use this many concurrent connections to vacuum\n" ));
887931 printf (_ (" --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n" ));
888932 printf (_ (" --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n" ));
933+ printf (_ (" -P, --parallel=PARALLEL_DEGREE use this many background workers for vacuum, if available\n" ));
889934 printf (_ (" -q, --quiet don't write any messages\n" ));
890935 printf (_ (" --skip-locked skip relations that cannot be immediately locked\n" ));
891936 printf (_ (" -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" ));
0 commit comments