Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1ucUVb-00DWTB-QJ for pgsql-hackers@arkaria.postgresql.org; Thu, 17 Jul 2025 19:43:12 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1ucUVY-005S12-QO for pgsql-hackers@arkaria.postgresql.org; Thu, 17 Jul 2025 19:43:09 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1ucUVY-005S0s-B1 for pgsql-hackers@lists.postgresql.org; Thu, 17 Jul 2025 19:43:09 +0000 Received: from mail-lj1-x236.google.com ([2a00:1450:4864:20::236]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1ucUVW-008JST-1k for pgsql-hackers@lists.postgresql.org; Thu, 17 Jul 2025 19:43:08 +0000 Received: by mail-lj1-x236.google.com with SMTP id 38308e7fff4ca-32ca160b4bcso13152731fa.3 for ; Thu, 17 Jul 2025 12:43:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1752781384; x=1753386184; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=Rb1Q0uYA4kVXQQWqbs1Z+l6fiwqHjvxIN0Q4gJW5nSQ=; b=QidYgpx0iDF0srpyzrKjh0FE+ZceQZ6sn114FKyOQu9b1WjlXm39Xn/RS6OdbBpMEE xouxhCVpbhVL4Lz7pmGtWtKDHmmVMaSbNw+URVoa0m2BIi4fUH7gyKviOD3IEPcYj7HH bomZG9TTDuz9OVNottGjMJGMhFxtyuYYREq/G4xzhkwysmtKr1/zPdVL5goKE0l1iECJ fbHyTLeHoTWivaxX0DoQhGwCTFIgRHFQ3U+fx9KCXXZ2ZQItwUwx5QygQ0rl8wwIx9Z8 Y0y/LgCayQlRErdjZfnyHWUMoNYZsND4+xTbsXS5MhYSZ22L9R8yVTEoYv3bPbvSBFoj G/kQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752781384; x=1753386184; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Rb1Q0uYA4kVXQQWqbs1Z+l6fiwqHjvxIN0Q4gJW5nSQ=; b=PoLP2YbzOB0m6MiyAnJbq6umog0Ye4Rl5XPuWbVncyJ0tkQYyTP4KN4RYWoH+trz1A qLl6gbOTDdbEyRv+n5gq0kuavFCoeFYGM97hs2L+edNsmm3+vGib3vPZY3piRn0rsiX1 RAZ5LRzOWINmflQvjIgxUEQEann4FnFNiXI7/H3+RGk2p+vCFFuKFf/PPTp8DX0ZUKeI YcruOYVBLANDCUNfO3ki1BL3ICp7gFN7278dnAOjAumMy04Y8OO3L+YMNaVSXnDk8cw1 MlFudna7BQ6V4gyIKxlwR+6Ig40AunAbZNysBeSrIG7pQzoKTAScFld710O4H4Ia3dun Wcrg== X-Forwarded-Encrypted: i=1; AJvYcCVIp1Y+3LlRq2nhx29pk38VDIWscg7Ef9+oBnTtA+Q5Eyq7Oe2gc371nIyQrTSxUk4qV5gDgk49O8xVu9ZC@lists.postgresql.org X-Gm-Message-State: AOJu0YytUJUxLIX0qgnZWTIFQcmKfHrLPMZbWdsL89WxagWW5n25W1ko jW+++KY2cqv9Pyvrh9SRg2pGg5WZI6wmASRlrvkP9N9ZZxYre/v4HvodIrrAttpxBa/Y55K6Z55 3yuZRzo3k0ujdG2oT9SHX73bRVq6PunHQUPJS X-Gm-Gg: ASbGncs5nBwHYpgz2tznblBIT89x4CeO0dFXm05TRQBobRTsY5MPW7wWNsrqarn5Rqy 0tTiAX8s7b9/XW2yqyrteKDECSf8IZngB0k5CVxZOn0DqYfi26i1fOO6IN8TXb5ibhZd6jHcnHT Cswc+kDU4+BglDZfeqRTx6h7UXq0JSqw/1kLjvNsgONUiB6uyBRkHRCG6Hv+TtwrZVu2X9BeCud 9d/5A== X-Google-Smtp-Source: AGHT+IENhse+29EFbz8O+zRctPmc92oMATLQNRwHwwPmm4bdrEwlyZfa7I72y00QutgOe6Otzt5VyOF/MYSlvY/Z6OA= X-Received: by 2002:a05:651c:2205:b0:32a:77a3:877f with SMTP id 38308e7fff4ca-3308e1ce11cmr26024781fa.2.1752781383816; Thu, 17 Jul 2025 12:43:03 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Masahiko Sawada Date: Thu, 17 Jul 2025 12:42:27 -0700 X-Gm-Features: Ac12FXw8uOswrXkkOSfcFuZvXq_97zfEma6E6Xw0ZzeNBsb01bYhd5F13jh9nFc Message-ID: Subject: Re: POC: Parallel processing of indexes in autovacuum To: Daniil Davydov <3danissimo@gmail.com> Cc: Matheus Alcantara , Sami Imseih , Maxim Orlov , Postgres hackers Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Mon, Jul 14, 2025 at 3:49=E2=80=AFAM Daniil Davydov <3danissimo@gmail.co= m> wrote: > > > > --- > > + nlaunched_workers =3D pvs->pcxt->nworkers_launched; /* remember thi= s 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 (aft= er > 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 =3D 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 >=3D 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 th= is + * moment, available workers number will not exceed limit after + * releasing them (see ParallelAutoVacuumReleaseWorkers). + */ + AutoVacuumShmem->av_freeParallelWorkers =3D + autovacuum_max_parallel_workers; I think the comment refers to the following code in AutoVacuumReleaseParallelWorkers(): + /* + * If autovacuum_max_parallel_workers variable was reduced during paral= lel + * autovacuum execution, we must cap available workers number by its ne= w + * value. + */ + if (AutoVacuumShmem->av_freeParallelWorkers > + autovacuum_max_parallel_workers) + { + AutoVacuumShmem->av_freeParallelWorkers =3D + 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 =3D 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, --=20 Masahiko Sawada Amazon Web Services: https://aws.amazon.com