guc_parallel_index_scan_v1.patch
application/octet-stream
Filename: guc_parallel_index_scan_v1.patch
Type: application/octet-stream
Part: 1
Message:
Re: Parallel Index Scans
Patch
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| doc/src/sgml/config.sgml | 18 | 4 |
| src/backend/optimizer/path/allpaths.c | 56 | 23 |
| src/backend/utils/misc/guc.c | 14 | 3 |
| src/backend/utils/misc/postgresql.conf.sample | 2 | 1 |
| src/include/optimizer/paths.h | 2 | 1 |
| src/test/regress/expected/select_parallel.out | 1 | 1 |
| src/test/regress/sql/select_parallel.sql | 1 | 1 |
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index dc63d7d..b4b7f0b 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -3835,20 +3835,34 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
</listitem>
</varlistentry>
- <varlistentry id="guc-min-parallel-relation-size" xreflabel="min_parallel_relation_size">
- <term><varname>min_parallel_relation_size</varname> (<type>integer</type>)
+ <varlistentry id="guc-min-parallel-table-scan-size" xreflabel="min_parallel_table_scan_size">
+ <term><varname>min_parallel_table_scan_size</varname> (<type>integer</type>)
<indexterm>
- <primary><varname>min_parallel_relation_size</> configuration parameter</primary>
+ <primary><varname>min_parallel_table_scan_size</> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
- Sets the minimum size of relations to be considered for parallel scan.
+ Sets the minimum size of tables to be considered for parallel scan.
The default is 8 megabytes (<literal>8MB</>).
</para>
</listitem>
</varlistentry>
+ <varlistentry id="guc-min-parallel-index-scan-size" xreflabel="min_parallel_index_scan_size">
+ <term><varname>min_parallel_index_scan_size</varname> (<type>integer</type>)
+ <indexterm>
+ <primary><varname>min_parallel_index_scan_size</> configuration parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the minimum size of indexes to be considered for parallel scan.
+ The default is 512 kilobytes (<literal>512kB</>).
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="guc-effective-cache-size" xreflabel="effective_cache_size">
<term><varname>effective_cache_size</varname> (<type>integer</type>)
<indexterm>
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 5c18987..85505c5 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -57,7 +57,8 @@ typedef struct pushdown_safety_info
/* These parameters are set by GUC */
bool enable_geqo = false; /* just in case GUC doesn't set it */
int geqo_threshold;
-int min_parallel_relation_size;
+int min_parallel_table_scan_size;
+int min_parallel_index_scan_size;
/* Hook for plugins to get control in set_rel_pathlist() */
set_rel_pathlist_hook_type set_rel_pathlist_hook = NULL;
@@ -126,7 +127,8 @@ static void subquery_push_qual(Query *subquery,
static void recurse_push_qual(Node *setOp, Query *topquery,
RangeTblEntry *rte, Index rti, Node *qual);
static void remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel);
-static int compute_parallel_worker(RelOptInfo *rel, BlockNumber pages);
+static int compute_parallel_worker(RelOptInfo *rel, BlockNumber heap_pages,
+ BlockNumber index_pages);
/*
@@ -679,7 +681,7 @@ create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel)
{
int parallel_workers;
- parallel_workers = compute_parallel_worker(rel, rel->pages);
+ parallel_workers = compute_parallel_worker(rel, rel->pages, 0);
/* If any limit was set to zero, the user doesn't want a parallel scan. */
if (parallel_workers <= 0)
@@ -2876,13 +2878,20 @@ remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel)
/*
* Compute the number of parallel workers that should be used to scan a
- * relation. "pages" is the number of pages from the relation that we
- * expect to scan.
+ * relation. We compute the parallel workers based on the size of the heap to
+ * be scanned and the size of the index to be scanned, then choose a minimum
+ * of those.
+ *
+ * "heap_pages" is the number of pages from the table that we expect to scan.
+ * "index_pages" is the number of pages from the index that we expect to scan.
*/
static int
-compute_parallel_worker(RelOptInfo *rel, BlockNumber pages)
+compute_parallel_worker(RelOptInfo *rel, BlockNumber heap_pages,
+ BlockNumber index_pages)
{
- int parallel_workers;
+ int parallel_workers = 0;
+ int heap_parallel_workers = 1;
+ int index_parallel_workers = 1;
/*
* If the user has set the parallel_workers reloption, use that; otherwise
@@ -2892,7 +2901,8 @@ compute_parallel_worker(RelOptInfo *rel, BlockNumber pages)
parallel_workers = rel->rel_parallel_workers;
else
{
- int parallel_threshold;
+ int heap_parallel_threshold;
+ int index_parallel_threshold;
/*
* If this relation is too small to be worth a parallel scan, just
@@ -2901,25 +2911,48 @@ compute_parallel_worker(RelOptInfo *rel, BlockNumber pages)
* might not be worthwhile just for this relation, but when combined
* with all of its inheritance siblings it may well pay off.
*/
- if (pages < (BlockNumber) min_parallel_relation_size &&
+ if (heap_pages < (BlockNumber) min_parallel_table_scan_size &&
+ index_pages < (BlockNumber) min_parallel_index_scan_size &&
rel->reloptkind == RELOPT_BASEREL)
return 0;
- /*
- * Select the number of workers based on the log of the size of the
- * relation. This probably needs to be a good deal more
- * sophisticated, but we need something here for now. Note that the
- * upper limit of the min_parallel_relation_size GUC is chosen to
- * prevent overflow here.
- */
- parallel_workers = 1;
- parallel_threshold = Max(min_parallel_relation_size, 1);
- while (pages >= (BlockNumber) (parallel_threshold * 3))
+ if (heap_pages > 0)
+ {
+ /*
+ * Select the number of workers based on the log of the size of
+ * the relation. This probably needs to be a good deal more
+ * sophisticated, but we need something here for now. Note that
+ * the upper limit of the min_parallel_table_scan_size GUC is
+ * chosen to prevent overflow here.
+ */
+ heap_parallel_threshold = Max(min_parallel_table_scan_size, 1);
+ while (heap_pages >= (BlockNumber) (heap_parallel_threshold * 3))
+ {
+ heap_parallel_workers++;
+ heap_parallel_threshold *= 3;
+ if (heap_parallel_threshold > INT_MAX / 3)
+ break; /* avoid overflow */
+ }
+
+ parallel_workers = heap_parallel_workers;
+ }
+
+ if (index_pages > 0)
{
- parallel_workers++;
- parallel_threshold *= 3;
- if (parallel_threshold > INT_MAX / 3)
- break; /* avoid overflow */
+ /* same calculation as for heap_pages above */
+ index_parallel_threshold = Max(min_parallel_index_scan_size, 1);
+ while (index_pages >= (BlockNumber) (index_parallel_threshold * 3))
+ {
+ index_parallel_workers++;
+ index_parallel_threshold *= 3;
+ if (index_parallel_threshold > INT_MAX / 3)
+ break; /* avoid overflow */
+ }
+
+ if (parallel_workers > 0)
+ parallel_workers = Min(parallel_workers, index_parallel_workers);
+ else
+ parallel_workers = index_parallel_workers;
}
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index de85eca..0df45b8 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2776,17 +2776,28 @@ static struct config_int ConfigureNamesInt[] =
},
{
- {"min_parallel_relation_size", PGC_USERSET, QUERY_TUNING_COST,
- gettext_noop("Sets the minimum size of relations to be considered for parallel scan."),
+ {"min_parallel_table_scan_size", PGC_USERSET, QUERY_TUNING_COST,
+ gettext_noop("Sets the minimum size of tables to be considered for parallel scan."),
NULL,
GUC_UNIT_BLOCKS,
},
- &min_parallel_relation_size,
+ &min_parallel_table_scan_size,
(8 * 1024 * 1024) / BLCKSZ, 0, INT_MAX / 3,
NULL, NULL, NULL
},
{
+ {"min_parallel_index_scan_size", PGC_USERSET, QUERY_TUNING_COST,
+ gettext_noop("Sets the minimum size of indexes to be considered for parallel scan."),
+ NULL,
+ GUC_UNIT_BLOCKS,
+ },
+ &min_parallel_index_scan_size,
+ (512 * 1024) / BLCKSZ, 0, INT_MAX / 3,
+ NULL, NULL, NULL
+ },
+
+ {
/* Can't be set in postgresql.conf */
{"server_version_num", PGC_INTERNAL, PRESET_OPTIONS,
gettext_noop("Shows the server version as an integer."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 661b0fa..157d775 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -300,7 +300,8 @@
#cpu_operator_cost = 0.0025 # same scale as above
#parallel_tuple_cost = 0.1 # same scale as above
#parallel_setup_cost = 1000.0 # same scale as above
-#min_parallel_relation_size = 8MB
+#min_parallel_table_scan_size = 8MB
+#min_parallel_index_scan_size = 512kB
#effective_cache_size = 4GB
# - Genetic Query Optimizer -
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index 81a9be7..81e7a42 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -22,7 +22,8 @@
*/
extern bool enable_geqo;
extern int geqo_threshold;
-extern int min_parallel_relation_size;
+extern int min_parallel_table_scan_size;
+extern int min_parallel_index_scan_size;
/* Hook for plugins to get control in set_rel_pathlist() */
typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out
index 18e21b7..b967b45 100644
--- a/src/test/regress/expected/select_parallel.out
+++ b/src/test/regress/expected/select_parallel.out
@@ -9,7 +9,7 @@ begin isolation level repeatable read;
-- encourage use of parallel plans
set parallel_setup_cost=0;
set parallel_tuple_cost=0;
-set min_parallel_relation_size=0;
+set min_parallel_table_scan_size=0;
set max_parallel_workers_per_gather=4;
explain (costs off)
select count(*) from a_star;
diff --git a/src/test/regress/sql/select_parallel.sql b/src/test/regress/sql/select_parallel.sql
index 8b4090f..e3c32de 100644
--- a/src/test/regress/sql/select_parallel.sql
+++ b/src/test/regress/sql/select_parallel.sql
@@ -12,7 +12,7 @@ begin isolation level repeatable read;
-- encourage use of parallel plans
set parallel_setup_cost=0;
set parallel_tuple_cost=0;
-set min_parallel_relation_size=0;
+set min_parallel_table_scan_size=0;
set max_parallel_workers_per_gather=4;
explain (costs off)