commit bbf3d7570b638a630b3d79a279fa4a2d572ebdf3 Author: jcoleman Date: Fri Nov 9 19:39:49 2018 +0000 Convert MAX_SAOP_ARRAY_SIZE into guc diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index b8e32d765b..24a3353501 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -4379,6 +4379,23 @@ ANY num_sync ( + array_optimization_size_limit (integer) + + array_optimization_size_limit configuration parameter + + + + + Sets the array size limit beyond which predicate optimization is not used. + The optimizer evaluates scalar array expressions to determine if they can + be treated as AND or OR clauses. This optimization proving is only performed + if the array contains at most this many items. + The default is 100. + + + + default_statistics_target (integer) diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c index 446207de30..cba6608ce2 100644 --- a/src/backend/optimizer/util/predtest.c +++ b/src/backend/optimizer/util/predtest.c @@ -33,9 +33,8 @@ * likely to require O(N^2) time, and more often than not fail anyway. * So we set an arbitrary limit on the number of array elements that * we will allow to be treated as an AND or OR clause. - * XXX is it worth exposing this as a GUC knob? */ -#define MAX_SAOP_ARRAY_SIZE 100 +int array_optimization_size_limit = ARRAY_OPTIMIZATION_SIZE_LIMIT; /* * To avoid redundant coding in predicate_implied_by_recurse and @@ -812,11 +811,11 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate, * If the expression is classified as AND- or OR-type, then *info is filled * in with the functions needed to iterate over its components. * - * This function also implements enforcement of MAX_SAOP_ARRAY_SIZE: if a + * This function also implements enforcement of array_optimization_size_limit: if a * ScalarArrayOpExpr's array has too many elements, we just classify it as an * atom. (This will result in its being passed as-is to the simple_clause * functions, which will fail to prove anything about it.) Note that we - * cannot just stop after considering MAX_SAOP_ARRAY_SIZE elements; in general + * cannot just stop after considering array_optimization_size_limit elements; in general * that would result in wrong proofs, rather than failing to prove anything. */ static PredClass @@ -874,7 +873,7 @@ predicate_classify(Node *clause, PredIterInfo info) arrayval = DatumGetArrayTypeP(((Const *) arraynode)->constvalue); nelems = ArrayGetNItems(ARR_NDIM(arrayval), ARR_DIMS(arrayval)); - if (nelems <= MAX_SAOP_ARRAY_SIZE) + if (nelems <= array_optimization_size_limit) { info->startup_fn = arrayconst_startup_fn; info->next_fn = arrayconst_next_fn; @@ -884,7 +883,7 @@ predicate_classify(Node *clause, PredIterInfo info) } else if (arraynode && IsA(arraynode, ArrayExpr) && !((ArrayExpr *) arraynode)->multidims && - list_length(((ArrayExpr *) arraynode)->elements) <= MAX_SAOP_ARRAY_SIZE) + list_length(((ArrayExpr *) arraynode)->elements) <= array_optimization_size_limit) { info->startup_fn = arrayexpr_startup_fn; info->next_fn = arrayexpr_next_fn; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index ce54828fbb..f1bc483b2e 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -52,6 +52,7 @@ #include "optimizer/geqo.h" #include "optimizer/paths.h" #include "optimizer/planmain.h" +#include "optimizer/predtest.h" #include "parser/parse_expr.h" #include "parser/parse_type.h" #include "parser/parser.h" @@ -3064,6 +3065,20 @@ static struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, + { + {"array_optimization_size_limit", PGC_USERSET, QUERY_TUNING_OTHER, + gettext_noop("Sets the array size limit beyond which predicate " + "optimization is not used."), + gettext_noop("The optimizer evaluates scalar array expressions " + "to determine if they can be treated as AND or OR clauses. " + "This optimization proving is only performed if the array " + "contains at most this many items.") + }, + &array_optimization_size_limit, + ARRAY_OPTIMIZATION_SIZE_LIMIT, 0, INT_MAX, + NULL, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 4e61bc6521..58d911950e 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -344,6 +344,7 @@ # - Other Planner Options - +#array_optimization_size_limit = 100 #default_statistics_target = 100 # range 1-10000 #constraint_exclusion = partition # on, off, or partition #cursor_tuple_fraction = 0.1 # range 0.0-1.0 diff --git a/src/include/optimizer/predtest.h b/src/include/optimizer/predtest.h index 69d87ea5c5..e8f6b91ef2 100644 --- a/src/include/optimizer/predtest.h +++ b/src/include/optimizer/predtest.h @@ -16,6 +16,8 @@ #include "nodes/primnodes.h" +#define ARRAY_OPTIMIZATION_SIZE_LIMIT 100 +extern PGDLLIMPORT int array_optimization_size_limit; extern bool predicate_implied_by(List *predicate_list, List *clause_list, bool weak); diff --git a/src/test/modules/test_predtest/expected/test_predtest.out b/src/test/modules/test_predtest/expected/test_predtest.out index 5574e03204..bca47107a9 100644 --- a/src/test/modules/test_predtest/expected/test_predtest.out +++ b/src/test/modules/test_predtest/expected/test_predtest.out @@ -767,6 +767,22 @@ w_i_holds | t s_r_holds | f w_r_holds | f +set array_optimization_size_limit to 1; +select * from test_predtest($$ +select x <= 3, x in (1,3) +from integers +$$); +-[ RECORD 1 ]-----+-- +strong_implied_by | f +weak_implied_by | f +strong_refuted_by | f +weak_refuted_by | f +s_i_holds | t +w_i_holds | t +s_r_holds | f +w_r_holds | f + +set array_optimization_size_limit to default; select * from test_predtest($$ select x <= 5, x in (1,3,5,7) from integers diff --git a/src/test/modules/test_predtest/sql/test_predtest.sql b/src/test/modules/test_predtest/sql/test_predtest.sql index 2734735843..39c6d383ad 100644 --- a/src/test/modules/test_predtest/sql/test_predtest.sql +++ b/src/test/modules/test_predtest/sql/test_predtest.sql @@ -301,6 +301,13 @@ select x <= 5, x in (1,3,5) from integers $$); +set array_optimization_size_limit to 1; +select * from test_predtest($$ +select x <= 3, x in (1,3) +from integers +$$); +set array_optimization_size_limit to default; + select * from test_predtest($$ select x <= 5, x in (1,3,5,7) from integers