From d36510fb3f2317b6194e78e83af1c22fcc27a7bd Mon Sep 17 00:00:00 2001
From: Seamus Abshere <seamus@abshere.net>
Date: Mon, 15 Feb 2021 10:34:32 -0500
Subject: [PATCH] Allow setting parallel_workers on partitioned tables.
To: pgsql-hackers@postgresql.org

Sometimes it's beneficial to do

ALTER TABLE my_part_tbl SET (parallel_workers = 32);

when the query planner is planning too few workers to read from your
partitions. For example, if you have a partitioned table where each
partition is a foreign table that cannot itself have this setting on it.
Shown to give a 100%+ performance increase (in my case, 700%) when used
with cstore_fdw column store partitions.
---
 src/backend/access/common/reloptions.c | 12 +++++++++---
 src/backend/optimizer/path/allpaths.c  | 16 ++++++++++++++++
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index c687d3ee9e..029a73325e 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1962,12 +1962,18 @@ bytea *
 partitioned_table_reloptions(Datum reloptions, bool validate)
 {
 	/*
-	 * There are no options for partitioned tables yet, but this is able to do
-	 * some validation.
+	 * Currently the only setting known to be useful for partitioned tables
+	 * is parallel_workers.
 	 */
+	static const relopt_parse_elt tab[] = {
+		{"parallel_workers", RELOPT_TYPE_INT,
+		offsetof(StdRdOptions, parallel_workers)},
+	};
+
 	return (bytea *) build_reloptions(reloptions, validate,
 									  RELOPT_KIND_PARTITIONED,
-									  0, NULL, 0);
+									  sizeof(StdRdOptions),
+									  tab, lengthof(tab));
 }
 
 /*
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index cd3fdd259c..4c4e17a8c6 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1467,6 +1467,14 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
 		ListCell   *lc;
 		int			parallel_workers = 0;
 
+		/* First see if there is a root-level setting for parallel_workers */
+		parallel_workers = compute_parallel_worker(
+			rel,
+			-1,
+			-1,
+			max_parallel_workers_per_gather
+		);
+
 		/* Find the highest number of workers requested for any subpath. */
 		foreach(lc, partial_subpaths)
 		{
@@ -1522,6 +1530,14 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
 		ListCell   *lc;
 		int			parallel_workers = 0;
 
+		/* First see if there is a root-level setting for parallel_workers */
+		parallel_workers = compute_parallel_worker(
+			rel,
+			-1,
+			-1,
+			max_parallel_workers_per_gather
+		);
+
 		/*
 		 * Find the highest number of workers requested for any partial
 		 * subpath.
-- 
2.27.0

