From 95cb115bbb21fd910c53eee4138d45ec2b8a9794 Mon Sep 17 00:00:00 2001 From: Jeff Davis Date: Sat, 21 Jan 2023 12:44:07 -0800 Subject: [PATCH v10 4/4] Introduce GUCs to control abbreviated keys sort optimization. The setting sort_abbreviated_keys turns the optimization on or off overall. The optimization relies on collation providers, which are complex dependencies, and the performance of the optimization may rely on many factors. Introducing a GUC allows easier diagnosis when this optimization results in worse perforamnce. The setting trust_strxfrm replaces the define TRUST_STRXFRM, allowing users to experiment with the abbreviated keys optimization when using the libc provider. Previously, the optimization only applied to collations using the ICU provider unless specially compiled. By default, allowed only for superusers (because an incorrect setting could lead to wrong results), but can be granted to others. --- doc/src/sgml/config.sgml | 40 ++++++++++++++++++++++ src/backend/utils/adt/pg_locale.c | 20 +++++------ src/backend/utils/misc/guc_tables.c | 24 +++++++++++++ src/backend/utils/sort/tuplesortvariants.c | 17 ++++++--- 4 files changed, 85 insertions(+), 16 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 8c56b134a8..f59a8518a0 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -11252,6 +11252,46 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' + + sort_abbreviated_keys (boolean) + + sort_abbreviated_keys configuration parameter + + + + + Enables or disables the use of abbreviated sort keys, a sort optimization, + if applicable. The default is true. Disabling may + be useful to diagnose problems or measure performance. + + + + + + trust_strxfrm (boolean) + + trust_strxfrm configuration parameter + + + + + Abbreviated keys, a sort optimization, depends on correct behavior of + the operating system function strxfrm() when + using a collation with the libc provider. On some + platforms strxfrm() does not return results + consistent with strcoll(), which means the + optimization could return wrong results. Set to + true if it is certain that + strxfrm() can be trusted. + + + The default value is false. This setting has no + effect if is set to + false. + + + + trace_locks (boolean) diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index c4b7c65088..d88f02aeb1 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -94,6 +94,9 @@ char *locale_monetary; char *locale_numeric; char *locale_time; +/* GUC to enable use of strxfrm() for abbreviated keys */ +bool trust_strxfrm = false; + /* * lc_time localization cache. * @@ -2105,17 +2108,16 @@ pg_strxfrm_libc(char *dest, const char *src, size_t destsize, { Assert(!locale || locale->provider == COLLPROVIDER_LIBC); -#ifdef TRUST_STRXFRM + /* shouldn't happen */ + if (!trust_strxfrm) + elog(ERROR, "unsupported collprovider: %c", locale->provider); + #ifdef HAVE_LOCALE_T if (locale) return strxfrm_l(dest, src, destsize, locale->info.lt); else #endif return strxfrm(dest, src, destsize); -#else - /* shouldn't happen */ - elog(ERROR, "unsupported collprovider: %c", locale->provider); -#endif } static size_t @@ -2302,7 +2304,7 @@ pg_strxfrm_prefix_icu(char *dest, const char *src, size_t destsize, * results. While no other libc other than Cygwin has so far been shown to * have a problem, we take the conservative course of action for right now and * disable this categorically. (Users who are certain this isn't a problem on - * their system can define TRUST_STRXFRM.) + * their system can set the developer GUC "trust_strxfrm".) * * No similar problem is known for the ICU provider. */ @@ -2310,11 +2312,7 @@ bool pg_strxfrm_enabled(pg_locale_t locale) { if (!locale || locale->provider == COLLPROVIDER_LIBC) -#ifdef TRUST_STRXFRM - return true; -#else - return false; -#endif + return trust_strxfrm; else if (locale->provider == COLLPROVIDER_ICU) return true; else diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index b46e3b8c55..a1e7eb7b99 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -102,6 +102,8 @@ extern bool trace_syncscan; #ifdef DEBUG_BOUNDED_SORT extern bool optimize_bounded_sort; #endif +extern bool sort_abbreviated_keys; +extern bool trust_strxfrm; /* * Options for enum values defined in this module. @@ -1673,6 +1675,28 @@ struct config_bool ConfigureNamesBool[] = }, #endif + { + {"sort_abbreviated_keys", PGC_USERSET, DEVELOPER_OPTIONS, + gettext_noop("Enables the use of abbreviated sort keys."), + NULL, + GUC_NOT_IN_SAMPLE | GUC_EXPLAIN + }, + &sort_abbreviated_keys, + true, + NULL, NULL, NULL + }, + + { + {"trust_strxfrm", PGC_SUSET, DEVELOPER_OPTIONS, + gettext_noop("Allow use of strxfrm() for abbreviated keys optimization for libc provider."), + NULL, + GUC_NOT_IN_SAMPLE + }, + &trust_strxfrm, + false, + NULL, NULL, NULL + }, + #ifdef WAL_DEBUG { {"wal_debug", PGC_SUSET, DEVELOPER_OPTIONS, diff --git a/src/backend/utils/sort/tuplesortvariants.c b/src/backend/utils/sort/tuplesortvariants.c index eb6cfcfd00..ba16779f97 100644 --- a/src/backend/utils/sort/tuplesortvariants.c +++ b/src/backend/utils/sort/tuplesortvariants.c @@ -37,6 +37,8 @@ #define DATUM_SORT 2 #define CLUSTER_SORT 3 +bool sort_abbreviated_keys = true; + static void removeabbrev_heap(Tuplesortstate *state, SortTuple *stups, int count); static void removeabbrev_cluster(Tuplesortstate *state, SortTuple *stups, @@ -185,7 +187,8 @@ tuplesort_begin_heap(TupleDesc tupDesc, sortKey->ssup_nulls_first = nullsFirstFlags[i]; sortKey->ssup_attno = attNums[i]; /* Convey if abbreviation optimization is applicable in principle */ - sortKey->abbreviate = (i == 0 && base->haveDatum1); + if (sort_abbreviated_keys) + sortKey->abbreviate = (i == 0 && base->haveDatum1); PrepareSortSupportFromOrderingOp(sortOperators[i], sortKey); } @@ -295,7 +298,8 @@ tuplesort_begin_cluster(TupleDesc tupDesc, (scanKey->sk_flags & SK_BT_NULLS_FIRST) != 0; sortKey->ssup_attno = scanKey->sk_attno; /* Convey if abbreviation optimization is applicable in principle */ - sortKey->abbreviate = (i == 0 && base->haveDatum1); + if (sort_abbreviated_keys) + sortKey->abbreviate = (i == 0 && base->haveDatum1); Assert(sortKey->ssup_attno != 0); @@ -379,7 +383,8 @@ tuplesort_begin_index_btree(Relation heapRel, (scanKey->sk_flags & SK_BT_NULLS_FIRST) != 0; sortKey->ssup_attno = scanKey->sk_attno; /* Convey if abbreviation optimization is applicable in principle */ - sortKey->abbreviate = (i == 0 && base->haveDatum1); + if (sort_abbreviated_keys) + sortKey->abbreviate = (i == 0 && base->haveDatum1); Assert(sortKey->ssup_attno != 0); @@ -499,7 +504,8 @@ tuplesort_begin_index_gist(Relation heapRel, sortKey->ssup_nulls_first = false; sortKey->ssup_attno = i + 1; /* Convey if abbreviation optimization is applicable in principle */ - sortKey->abbreviate = (i == 0 && base->haveDatum1); + if (sort_abbreviated_keys) + sortKey->abbreviate = (i == 0 && base->haveDatum1); Assert(sortKey->ssup_attno != 0); @@ -573,7 +579,8 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, * can't, because a datum sort only stores a single copy of the datum; the * "tuple" field of each SortTuple is NULL. */ - base->sortKeys->abbreviate = !typbyval; + if (sort_abbreviated_keys) + base->sortKeys->abbreviate = !typbyval; PrepareSortSupportFromOrderingOp(sortOperator, base->sortKeys); -- 2.34.1