diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index cd234db..175b2c6 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) + + + Sets the degree of parallelism for an individual relation. The requested + number of workers will be limited by . + + + + + autovacuum_enabled, toast.autovacuum_enabled (boolean) diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index ea0755a..8e4aa80 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -26,6 +26,7 @@ #include "commands/tablespace.h" #include "commands/view.h" #include "nodes/makefuncs.h" +#include "postmaster/postmaster.h" #include "utils/array.h" #include "utils/attoptcache.h" #include "utils/builtins.h" @@ -267,6 +268,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, 0, MAX_BACKENDS + }, /* list terminator */ {{NULL}} @@ -1251,8 +1261,8 @@ fillRelOptions(void *rdopts, Size basesize, /* - * Option parser for anything that uses StdRdOptions (i.e. fillfactor and - * autovacuum) + * Option parser for anything that uses StdRdOptions (i.e. fillfactor, + * autovacuum and parallel_degree) */ bytea * default_reloptions(Datum reloptions, bool validate, relopt_kind kind) @@ -1291,7 +1301,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 cc77ff9..6032b95 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 5bdeac0..68ce936 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 6f24b03..2175de3 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 688d92a..2e102e7 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -1783,6 +1783,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 d39c73b..72fc91f 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..8f1cd85 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)) /* + * RelationGetParallelDegree + * Returns the relation's parallel_degree. Note multiple eval of argument! + */ +#define RelationGetParallelDegree(relation, defaultpd) \ + ((relation)->rd_options ? \ + ((StdRdOptions *) (relation)->rd_options)->parallel_degree : (defaultpd)) + +/* * RelationGetTargetPageUsage * Returns the relation's desired space usage per page in bytes. */