From 1534f2539b3728d97852ac9e098f38a7d2bb13fa Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Thu, 16 Jan 2025 15:35:03 -0800 Subject: [PATCH v13 1/5] Introduces table AM APIs for parallel table vacuuming. This commit introduces the following new table AM APIs for parallel heap vacuuming: - parallel_vacuum_compute_workers - parallel_vacuum_estimate - parallel_vacuum_initialize - parallel_vacuum_initialize_worker - parallel_vacuum_collect_dead_items There is no code using these new APIs for now. Upcoming parallel vacuum patches utilize these APIs. Reviewed-by: Discussion: https://postgr.es/m/ --- src/backend/access/heap/heapam_handler.c | 4 +- src/backend/access/heap/vacuumlazy.c | 12 ++ src/backend/access/table/tableamapi.c | 11 ++ src/include/access/heapam.h | 2 + src/include/access/tableam.h | 140 +++++++++++++++++++++++ 5 files changed, 168 insertions(+), 1 deletion(-) diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 24d3765aa20..a534100692a 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -2710,7 +2710,9 @@ static const TableAmRoutine heapam_methods = { .scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple, .scan_sample_next_block = heapam_scan_sample_next_block, - .scan_sample_next_tuple = heapam_scan_sample_next_tuple + .scan_sample_next_tuple = heapam_scan_sample_next_tuple, + + .parallel_vacuum_compute_workers = heap_parallel_vacuum_compute_workers, }; diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 2cbcf5e5db2..b4100dacd1d 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -3741,6 +3741,18 @@ update_relstats_all_indexes(LVRelState *vacrel) } } +/* + * Compute the number of workers for parallel heap vacuum. + * + * Return 0 to disable parallel vacuum. + */ +int +heap_parallel_vacuum_compute_workers(Relation rel, int nworkers_requested, + void *state) +{ + return 0; +} + /* * Error context callback for errors occurring during vacuum. The error * context messages for index phases should match the messages set in parallel diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c index 476663b66aa..c3ee9869e12 100644 --- a/src/backend/access/table/tableamapi.c +++ b/src/backend/access/table/tableamapi.c @@ -81,6 +81,7 @@ GetTableAmRoutine(Oid amhandler) Assert(routine->relation_copy_data != NULL); Assert(routine->relation_copy_for_cluster != NULL); Assert(routine->relation_vacuum != NULL); + Assert(routine->parallel_vacuum_compute_workers != NULL); Assert(routine->scan_analyze_next_block != NULL); Assert(routine->scan_analyze_next_tuple != NULL); Assert(routine->index_build_range_scan != NULL); @@ -94,6 +95,16 @@ GetTableAmRoutine(Oid amhandler) Assert(routine->scan_sample_next_block != NULL); Assert(routine->scan_sample_next_tuple != NULL); + /* + * Callbacks for parallel vacuum are also optional (except for + * parallel_vacuum_compute_workers). But one callback implies presence of + * the others. + */ + Assert(((((routine->parallel_vacuum_estimate == NULL) == + (routine->parallel_vacuum_initialize == NULL)) == + (routine->parallel_vacuum_initialize_worker == NULL)) == + (routine->parallel_vacuum_collect_dead_items == NULL))); + return routine; } diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 1640d9c32f7..6a1ca5d5ca7 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -409,6 +409,8 @@ extern void log_heap_prune_and_freeze(Relation relation, Buffer buffer, struct VacuumParams; extern void heap_vacuum_rel(Relation rel, struct VacuumParams *params, BufferAccessStrategy bstrategy); +extern int heap_parallel_vacuum_compute_workers(Relation rel, int nworkers_requested, + void *state); /* in heap/heapam_visibility.c */ extern bool HeapTupleSatisfiesVisibility(HeapTuple htup, Snapshot snapshot, diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h index b8cb1e744ad..c61b1700953 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -35,6 +35,9 @@ extern PGDLLIMPORT bool synchronize_seqscans; struct BulkInsertStateData; struct IndexInfo; +struct ParallelContext; +struct ParallelVacuumState; +struct ParallelWorkerContext; struct SampleScanState; struct VacuumParams; struct ValidateIndexState; @@ -655,6 +658,81 @@ typedef struct TableAmRoutine struct VacuumParams *params, BufferAccessStrategy bstrategy); + /* ------------------------------------------------------------------------ + * Callbacks for parallel table vacuum. + * ------------------------------------------------------------------------ + */ + + /* + * Compute the number of parallel workers for parallel table vacuum. The + * parallel degree for parallel vacuum is further limited by + * max_parallel_maintenance_workers. The function must return 0 to disable + * parallel table vacuum. + * + * 'nworkers_requested' is a >=0 number and the requested number of + * workers. This comes from the PARALLEL option. 0 means to choose the + * parallel degree based on the table AM specific factors such as table + * size. + */ + int (*parallel_vacuum_compute_workers) (Relation rel, + int nworkers_requested, + void *state); + + /* + * Estimate the size of shared memory needed for a parallel table vacuum + * of this relation. + * + * Not called if parallel table vacuum is disabled. + * + * Optional callback, but either all other parallel vacuum callbacks need + * to exist, or neither. + */ + void (*parallel_vacuum_estimate) (Relation rel, + struct ParallelContext *pcxt, + int nworkers, + void *state); + + /* + * Initialize DSM space for parallel table vacuum. + * + * Not called if parallel table vacuum is disabled. + * + * Optional callback, but either all other parallel vacuum callbacks need + * to exist, or neither. + */ + void (*parallel_vacuum_initialize) (Relation rel, + struct ParallelContext *pctx, + int nworkers, + void *state); + + /* + * Initialize AM-specific vacuum state for worker processes. + * + * The state_out is the output parameter so that arbitrary data can be + * passed to the subsequent callback, parallel_vacuum_remove_dead_items. + * + * Not called if parallel table vacuum is disabled. + * + * Optional callback, but either all other parallel vacuum callbacks need + * to exist, or neither. + */ + void (*parallel_vacuum_initialize_worker) (Relation rel, + struct ParallelVacuumState *pvs, + struct ParallelWorkerContext *pwcxt, + void **state_out); + + /* + * Execute a parallel scan to collect dead items. + * + * Not called if parallel table vacuum is disabled. + * + * Optional callback, but either all other parallel vacuum callbacks need + * to exist, or neither. + */ + void (*parallel_vacuum_collect_dead_items) (Relation rel, + struct ParallelVacuumState *pvs, + void *state); + /* * Prepare to analyze block `blockno` of `scan`. The scan has been started * with table_beginscan_analyze(). See also @@ -1680,6 +1758,68 @@ table_relation_vacuum(Relation rel, struct VacuumParams *params, rel->rd_tableam->relation_vacuum(rel, params, bstrategy); } +/* ---------------------------------------------------------------------------- + * Parallel vacuum related functions. + * ---------------------------------------------------------------------------- + */ + +/* + * Compute the number of parallel workers for a parallel vacuum scan of this + * relation. + */ +static inline int +table_parallel_vacuum_compute_workers(Relation rel, int nworkers_requested, + void *state) +{ + return rel->rd_tableam->parallel_vacuum_compute_workers(rel, + nworkers_requested, + state); +} + +/* + * Estimate the size of shared memory needed for a parallel vacuum scan of this + * of this relation. + */ +static inline void +table_parallel_vacuum_estimate(Relation rel, struct ParallelContext *pcxt, + int nworkers, void *state) +{ + Assert(nworkers > 0); + rel->rd_tableam->parallel_vacuum_estimate(rel, pcxt, nworkers, state); +} + +/* + * Initialize shared memory area for a parallel vacuum scan of this relation. + */ +static inline void +table_parallel_vacuum_initialize(Relation rel, struct ParallelContext *pcxt, + int nworkers, void *state) +{ + Assert(nworkers > 0); + rel->rd_tableam->parallel_vacuum_initialize(rel, pcxt, nworkers, state); +} + +/* + * Initialize AM-specific vacuum state for worker processes. + */ +static inline void +table_parallel_vacuum_initialize_worker(Relation rel, struct ParallelVacuumState *pvs, + struct ParallelWorkerContext *pwcxt, + void **state_out) +{ + rel->rd_tableam->parallel_vacuum_initialize_worker(rel, pvs, pwcxt, state_out); +} + +/* + * Execute a parallel vacuum scan to collect dead items. + */ +static inline void +table_parallel_vacuum_collect_dead_items(Relation rel, struct ParallelVacuumState *pvs, + void *state) +{ + rel->rd_tableam->parallel_vacuum_collect_dead_items(rel, pvs, state); +} + /* * Prepare to analyze the next block in the read stream. The scan needs to * have been started with table_beginscan_analyze(). Note that this routine -- 2.43.5