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.
*/