Re: POC: Parallel processing of indexes in autovacuum - Mailing list pgsql-hackers
From | Masahiko Sawada |
---|---|
Subject | Re: POC: Parallel processing of indexes in autovacuum |
Date | |
Msg-id | CAD21AoCcHKKXsr9Oh736ejckqqS1i430xGEyJ=JP5OL0ExyP1A@mail.gmail.com Whole thread Raw |
In response to | Re: POC: Parallel processing of indexes in autovacuum (Daniil Davydov <3danissimo@gmail.com>) |
List | pgsql-hackers |
On Mon, Jul 14, 2025 at 3:49 AM Daniil Davydov <3danissimo@gmail.com> wrote: > > > > --- > > + nlaunched_workers = pvs->pcxt->nworkers_launched; /* remember this value */ > > DestroyParallelContext(pvs->pcxt); > > + > > + /* Release all launched (i.e. reserved) parallel autovacuum workers. */ > > + if (AmAutoVacuumWorkerProcess()) > > + ParallelAutoVacuumReleaseWorkers(nlaunched_workers); > > + > > > > Why don't we release workers before destroying the parallel context? > > > > Destroying parallel context includes waiting for all workers to exit (after > which, other operations can use them). > If we first call ParallelAutoVacuumReleaseWorkers, some operation can > reasonably request all released workers. But this request can fail, > because there is no guarantee that workers managed to finish. > > Actually, there's nothing wrong with that, but I think releasing workers > only after finishing work is a more logical approach. > > > --- > > @@ -706,16 +751,16 @@ > > parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int > > num_index_scan > > > > if (vacuum) > > ereport(pvs->shared->elevel, > > - (errmsg(ngettext("launched %d parallel vacuum > > worker for index vacuuming (planned: %d)", > > - "launched %d parallel vacuum > > workers for index vacuuming (planned: %d)", > > + (errmsg(ngettext("launched %d parallel %svacuum > > worker for index vacuuming (planned: %d)", > > + "launched %d parallel %svacuum > > workers for index vacuuming (planned: %d)", > > pvs->pcxt->nworkers_launched), > > - pvs->pcxt->nworkers_launched, nworkers))); > > + pvs->pcxt->nworkers_launched, > > AmAutoVacuumWorkerProcess() ? "auto" : "", nworkers))); > > > > The "%svacuum" part doesn't work in terms of translation. We need to > > construct the whole sentence instead. > > But do we need this log message > > change in the first place? IIUC autovacuums write logs only when the > > execution time exceed the log_autovacuum_min_duration (or its > > reloption). The patch unconditionally sets LOG level for autovacuums > > but I'm not sure it's consistent with other autovacuum logging > > behavior: > > > > + int elevel = AmAutoVacuumWorkerProcess() || > > + vacrel->verbose ? > > + INFO : DEBUG2; > > > > > > This log level is used only "for messages about parallel workers launched". > I think that such logs relate more to the parallel workers module than > autovacuum itself. Moreover, if we emit log "planned vs. launched" each > time, it will simplify the task of selecting the optimal value of > 'autovacuum_max_parallel_workers' parameter. What do you think? INFO level is normally not sent to the server log. And regarding autovacuums, they don't write any log mentioning it started. If we want to write planned vs. launched I think it's better to gather these statistics during execution and write it together with other existing logs. > > About "%svacuum" - I guess we need to clarify what exactly the workers > were launched for. I'll add errhint to this log, but I don't know whether such > approach is acceptable. I'm not sure errhint is an appropriate place. If we write such information together with other existing autovacuum logs as I suggested above, I think we don't need to add such information to this log message. I've reviewed v7 patch and here are some comments: + { + { + "parallel_autovacuum_workers", + "Maximum number of parallel autovacuum workers that can be taken from bgworkers pool for processing this table. " + "If value is 0 then parallel degree will computed based on number of indexes.", + RELOPT_KIND_HEAP, + ShareUpdateExclusiveLock + }, + -1, -1, 1024 + }, Many autovacuum related reloptions have the prefix "autovacuum". So how about renaming it to autovacuum_parallel_worker (change check_parallel_av_gucs() name too accordingly)? --- +bool +check_autovacuum_max_parallel_workers(int *newval, void **extra, + GucSource source) +{ + if (*newval >= max_worker_processes) + return false; + return true; +} I think we don't need to strictly check the autovacuum_max_parallel_workers value. Instead, we can accept any integer value but internally cap by max_worker_processes. --- +/* + * Make sure that number of available parallel workers corresponds to the + * autovacuum_max_parallel_workers parameter (after it was changed). + */ +static void +check_parallel_av_gucs(int prev_max_parallel_workers) +{ I think this function doesn't just check the value but does adjust the number of available workers, so how about adjust_free_parallel_workers() or something along these lines? --- + /* + * Number of available workers must not exceed limit. + * + * Note, that if some parallel autovacuum workers are running at this + * moment, available workers number will not exceed limit after + * releasing them (see ParallelAutoVacuumReleaseWorkers). + */ + AutoVacuumShmem->av_freeParallelWorkers = + autovacuum_max_parallel_workers; I think the comment refers to the following code in AutoVacuumReleaseParallelWorkers(): + /* + * If autovacuum_max_parallel_workers variable was reduced during parallel + * autovacuum execution, we must cap available workers number by its new + * value. + */ + if (AutoVacuumShmem->av_freeParallelWorkers > + autovacuum_max_parallel_workers) + { + AutoVacuumShmem->av_freeParallelWorkers = + autovacuum_max_parallel_workers; + } After the autovacuum launchers decreases av_freeParallelWorkers, it's not guaranteed that the autovacuum worker already reflects the new value from the config file when executing the AutoVacuumReleaseParallelWorkers(), which leds to skips the above codes. For example, suppose that autovacuum_max_parallel_workers is 10 and 3 parallel workers are running by one autovacuum worker (i.e., av_freeParallelWorkers = 7 now), if the user changes autovacuum_max_parallel_workers to 5, the autovacuum launchers adjust av_freeParallelWorkers to 5. However, if the worker doesn't reload the config file and executes AutoVacuumReleaseParallelWorkers(), it increases av_freeParallelWorkers to 8 and skips the adjusting logic. I've not tested this scenarios so I might be missing something though. Regards, -- Masahiko Sawada Amazon Web Services: https://aws.amazon.com
pgsql-hackers by date: