diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index cd234db..80e1f09 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -909,6 +909,17 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI + parallel_degree (integer) + + + Number of workers wanted for this table. The number of worker will be + limited according to the + parameter. + + + + + autovacuum_enabled, toast.autovacuum_enabled (boolean) diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index ea0755a..68bb133 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -267,6 +267,15 @@ static relopt_int intRelOpts[] = 0, 0, 0 #endif }, + { + { + "parallel_degree", + "Number of parallel processes per executor node wanted for this relation.", + RELOPT_KIND_HEAP, + AccessExclusiveLock + }, + -1, 1, INT_MAX + }, /* list terminator */ {{NULL}} @@ -1291,7 +1300,9 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) {"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL, offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, analyze_scale_factor)}, {"user_catalog_table", RELOPT_TYPE_BOOL, - offsetof(StdRdOptions, user_catalog_table)} + offsetof(StdRdOptions, user_catalog_table)}, + {"parallel_degree", RELOPT_TYPE_INT, + offsetof(StdRdOptions, parallel_degree)} }; options = parseRelOptions(reloptions, validate, kind, &numoptions); diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index e1a5d33..d5de997 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -669,21 +669,31 @@ create_parallel_paths(PlannerInfo *root, RelOptInfo *rel) * just for this relation, but when combined with all of its inheritance siblings * it may well pay off. */ - if (rel->pages < parallel_threshold && rel->reloptkind == RELOPT_BASEREL) + if (rel->pages < parallel_threshold && rel->rel_parallel_degree == -1 && + rel->reloptkind == RELOPT_BASEREL) return; /* - * Limit the degree of parallelism logarithmically based on the size of the - * relation. This probably needs to be a good deal more sophisticated, but we - * need something here for now. + * Use the table parallel_degree if specified, but don't go further than + * max_parallel_degree */ - while (rel->pages > parallel_threshold * 3 && - parallel_degree < max_parallel_degree) + if (rel->rel_parallel_degree > 0) + parallel_degree = Min(rel->rel_parallel_degree, max_parallel_degree); + else { - parallel_degree++; - parallel_threshold *= 3; - if (parallel_threshold >= PG_INT32_MAX / 3) - break; + /* + * Limit the degree of parallelism logarithmically based on the size of the + * relation. This probably needs to be a good deal more sophisticated, but we + * need something here for now. + */ + while (rel->pages > parallel_threshold * 3 && + parallel_degree < max_parallel_degree) + { + parallel_degree++; + parallel_threshold *= 3; + if (parallel_threshold >= PG_INT32_MAX / 3) + break; + } } /* Add an unordered partial path based on a parallel sequential scan. */ diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 546067b..92feefc 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -128,6 +128,8 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, estimate_rel_size(relation, rel->attr_widths - rel->min_attr, &rel->pages, &rel->tuples, &rel->allvisfrac); + /* Setup the per-relation parallel_degree */ + rel->rel_parallel_degree = RelationGetParallelDegree(relation, -1); /* * Make list of indexes. Ignore indexes on system catalogs if told to. * Don't bother with indexes for an inheritance parent, either. diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 7e37edf..1650e1f 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -107,6 +107,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) rel->consider_startup = (root->tuple_fraction > 0); rel->consider_param_startup = false; /* might get changed later */ rel->consider_parallel = false; /* might get changed later */ + rel->rel_parallel_degree = -1; /* set up in GetRelationInfo */ rel->reltarget = create_empty_pathtarget(); rel->pathlist = NIL; rel->ppilist = NIL; diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 6a81416..e8b00ca 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -1782,6 +1782,7 @@ psql_completion(const char *text, int start, int end) "autovacuum_vacuum_scale_factor", "autovacuum_vacuum_threshold", "fillfactor", + "parallel_degree", "log_autovacuum_min_duration", "toast.autovacuum_enabled", "toast.autovacuum_freeze_max_age", diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index ee7007a..f47ff7c 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -521,6 +521,7 @@ typedef struct RelOptInfo double allvisfrac; PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ + int rel_parallel_degree; /* wanted number of parallel workers */ /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index f2bebf2..8bf5dbc 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -203,6 +203,7 @@ typedef struct StdRdOptions AutoVacOpts autovacuum; /* autovacuum-related options */ bool user_catalog_table; /* use as an additional catalog * relation */ + int parallel_degree; /* max number of parallel worker */ } StdRdOptions; #define HEAP_MIN_FILLFACTOR 10 @@ -217,6 +218,14 @@ typedef struct StdRdOptions ((StdRdOptions *) (relation)->rd_options)->fillfactor : (defaultff)) /* + * RelationGetMaxParallelDegree + * Returns the relation's parallel_degree. Note multiple eval of argument! + */ +#define RelationGetParallelDegree(relation, defaultmpd) \ + ((relation)->rd_options ? \ + ((StdRdOptions *) (relation)->rd_options)->parallel_degree : (defaultmpd)) + +/* * RelationGetTargetPageUsage * Returns the relation's desired space usage per page in bytes. */