diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 7a48973b3c..d440429a2c 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -5919,6 +5919,23 @@ SELECT * FROM parent WHERE key = 2400; + + recursive_worktable_estimate (floating point) + + recursive_worktable_estimate configuration parameter + + + + + Sets the planner's estimate of the average size of the worktable as a multiple of + the initial non-recursive term of the query. The default is 10.0. + This helps the planner choose the most appropriate method for joining the worktable + to the query's other tables. A setting of 1.0 is appropriate for shortest path + queries; graph analytics queries may benefit from larger values. + + + + diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 4d9f3b4bb6..4015efb314 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_estimate = DEFAULT_RECURSIVE_WORKTABLE_ESTIMATE; int effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE; @@ -5664,11 +5665,20 @@ set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel, double cte_rows) if (rte->self_reference) { + double multiplier = recursive_worktable_estimate; + + /* + * Reserve zero as a special case meaning use-the-built-in-calculation. + */ + if (recursive_worktable_estimate == 0.0) + multiplier = DEFAULT_RECURSIVE_WORKTABLE_ESTIMATE; + /* - * In a self-reference, arbitrarily assume the average worktable size - * is about 10 times the nonrecursive term's size. + * Use recursive_worktable_estimate to get average size of worktable, + * across all iterations. This will vary depending upon how bushy the + * data is, so allow the user to set based upon their data. */ - rel->tuples = 10 * cte_rows; + rel->tuples = clamp_row_est(multiplier * cte_rows); } else { diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 932aefc777..677fdcc46f 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -3740,6 +3740,19 @@ static struct config_real ConfigureNamesReal[] = NULL, NULL, NULL }, + { + {"recursive_worktable_estimate", PGC_USERSET, QUERY_TUNING_OTHER, + gettext_noop("Sets the planner's estimate of the average size " + "of the worktable as a multiple of the initial " + "non-recursive term of the query."), + NULL, + GUC_EXPLAIN + }, + &recursive_worktable_estimate, + DEFAULT_RECURSIVE_WORKTABLE_ESTIMATE, 0.0, 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..c7eeb11a17 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_estimate = 10.0 # Set to 1.0 for shortest path queries #------------------------------------------------------------------------------ diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 356a51f370..1afaae5e61 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 +#define DEFAULT_RECURSIVE_WORKTABLE_ESTIMATE 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..5e60f0bb27 100644 --- a/src/include/optimizer/optimizer.h +++ b/src/include/optimizer/optimizer.h @@ -92,6 +92,7 @@ extern PGDLLIMPORT double cpu_operator_cost; extern PGDLLIMPORT double parallel_tuple_cost; extern PGDLLIMPORT double parallel_setup_cost; extern PGDLLIMPORT int effective_cache_size; +extern PGDLLIMPORT double recursive_worktable_estimate; extern double clamp_row_est(double nrows);