diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 7a48973b3c..05df48131d 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -5919,6 +5919,29 @@ SELECT * FROM parent WHERE key = 2400; + + recursive_worktable_factor (floating point) + + recursive_worktable_factor configuration parameter + + + + + Sets the planner's estimate of the average size of the working + table of a recursive + query, as a multiple of the estimated size of the initial + non-recursive term of the query. This helps the planner choose + the most appropriate method for joining the working table to the + query's other tables. + The default value is 10.0. A smaller value + such as 1.0 can be helpful when the recursion + has low fan-out from one step to the next, as for + example in shortest-path queries. Graph analytics queries may + benefit from larger-than-default values. + + + + diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 4d9f3b4bb6..1b07ea392d 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -123,6 +123,7 @@ double cpu_index_tuple_cost = DEFAULT_CPU_INDEX_TUPLE_COST; double cpu_operator_cost = DEFAULT_CPU_OPERATOR_COST; double parallel_tuple_cost = DEFAULT_PARALLEL_TUPLE_COST; double parallel_setup_cost = DEFAULT_PARALLEL_SETUP_COST; +double recursive_worktable_factor = DEFAULT_RECURSIVE_WORKTABLE_FACTOR; int effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE; @@ -5665,10 +5666,11 @@ set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel, double cte_rows) if (rte->self_reference) { /* - * In a self-reference, arbitrarily assume the average worktable size - * is about 10 times the nonrecursive term's size. + * In a self-reference, we assume the average worktable size is a + * multiple of the nonrecursive term's size. The best multiplier will + * vary depending on query "fan-out", so make its value adjustable. */ - rel->tuples = 10 * cte_rows; + rel->tuples = clamp_row_est(recursive_worktable_factor * cte_rows); } else { diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index f70f7f5c01..b86137dc38 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -3740,6 +3740,18 @@ static struct config_real ConfigureNamesReal[] = NULL, NULL, NULL }, + { + {"recursive_worktable_factor", PGC_USERSET, QUERY_TUNING_OTHER, + gettext_noop("Sets the planner's estimate of the average size " + "of a recursive query's working table."), + NULL, + GUC_EXPLAIN + }, + &recursive_worktable_factor, + DEFAULT_RECURSIVE_WORKTABLE_FACTOR, 0.001, 1000000.0, + NULL, NULL, NULL + }, + { {"geqo_selection_bias", PGC_USERSET, QUERY_TUNING_GEQO, gettext_noop("GEQO: selective pressure within the population."), diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 4cf5b26a36..b933fade8c 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -426,6 +426,7 @@ # JOIN clauses #plan_cache_mode = auto # auto, force_generic_plan or # force_custom_plan +#recursive_worktable_factor = 10.0 # range 0.001-1000000 #------------------------------------------------------------------------------ diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 356a51f370..bc12071af6 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -29,6 +29,8 @@ #define DEFAULT_PARALLEL_TUPLE_COST 0.1 #define DEFAULT_PARALLEL_SETUP_COST 1000.0 +/* defaults for non-Cost parameters */ +#define DEFAULT_RECURSIVE_WORKTABLE_FACTOR 10.0 #define DEFAULT_EFFECTIVE_CACHE_SIZE 524288 /* measured in pages */ typedef enum diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h index 6b8ee0c69f..2302ab6d54 100644 --- a/src/include/optimizer/optimizer.h +++ b/src/include/optimizer/optimizer.h @@ -91,6 +91,7 @@ extern PGDLLIMPORT double cpu_index_tuple_cost; extern PGDLLIMPORT double cpu_operator_cost; extern PGDLLIMPORT double parallel_tuple_cost; extern PGDLLIMPORT double parallel_setup_cost; +extern PGDLLIMPORT double recursive_worktable_factor; extern PGDLLIMPORT int effective_cache_size; extern double clamp_row_est(double nrows);