From 49c8592c9729ab26005fa53385759fbecc2de327 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Fri, 23 Oct 2026 07:36:30 -0400 Subject: [PATCH v2 2/3] Add debug_topn_quickselect GUC (for testing, not for commit) Setting it to off makes bounded sorts use the heap as before, so the two methods can be compared on one server without a rebuild. --- src/backend/utils/misc/guc_parameters.dat | 7 +++++++ src/backend/utils/sort/tuplesort.c | 3 ++- src/include/utils/guc.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat index 380679a76c0..756d19a6680 100644 --- a/src/backend/utils/misc/guc_parameters.dat +++ b/src/backend/utils/misc/guc_parameters.dat @@ -731,6 +731,13 @@ ifdef => 'DEBUG_NODE_TESTS_ENABLED', }, +{ name => 'debug_topn_quickselect', type => 'bool', context => 'PGC_USERSET', group => 'DEVELOPER_OPTIONS', + short_desc => 'Uses quickselect instead of a heap for large bounded (top-N) sorts.', + flags => 'GUC_NOT_IN_SAMPLE', + variable => 'debug_topn_quickselect', + boot_val => 'true', +}, + { name => 'debug_write_read_parse_plan_trees', type => 'bool', context => 'PGC_SUSET', group => 'DEVELOPER_OPTIONS', short_desc => 'Set this to force all parse and plan trees to be passed through outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in those modules.', flags => 'GUC_NOT_IN_SAMPLE', diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 7650c8ef806..7de34da217a 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -131,6 +131,7 @@ StaticAssertDecl(TOPN_SELECT_MIN_BUFFER < INITIAL_MEMTUPSIZE, /* GUC variables */ bool trace_sort = false; +bool debug_topn_quickselect = true; #ifdef DEBUG_BOUNDED_SORT bool optimize_bounded_sort = true; @@ -1153,7 +1154,7 @@ tuplesort_puttuple_common(Tuplesortstate *state, SortTuple *tuple, * If 2 * bound tuples fit in memory, keep a buffer of them and * prune it back to bound with quickselect whenever it fills. */ - if (state->bound > 0 && !LACKMEM(state)) + if (debug_topn_quickselect && state->bound > 0 && !LACKMEM(state)) { if (trace_sort) elog(LOG, "switching to bounded quickselect at %d tuples: %s", diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 164efba6b51..13171f97c3c 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -327,6 +327,7 @@ extern PGDLLIMPORT int tcp_user_timeout; extern PGDLLIMPORT char *role_string; extern PGDLLIMPORT bool in_hot_standby_guc; extern PGDLLIMPORT bool trace_sort; +extern PGDLLIMPORT bool debug_topn_quickselect; #ifdef DEBUG_BOUNDED_SORT extern PGDLLIMPORT bool optimize_bounded_sort; -- 2.54.0