From 3e71ec0c22617756a8ca927dbf956d3ac0034478 Mon Sep 17 00:00:00 2001 From: "ZizhuanLiu(X-MAN)" <44973863@qq.com> Date: Thu, 20 Aug 2026 14:43:56 +0800 Subject: [PATCH v4] Fix var_eq_const: sum selectivity of all matching MCV When the column statistics have deterministic collation and the constant has non-deterministic collation. discussion: https://www.postgresql.org/message-id/flat/tencent_A15A9D89A86F2E4B086ABA462578B9B64307@qq.com commitfest: https://commitfest.postgresql.org/patch/7075/ --- src/backend/utils/adt/selfuncs.c | 47 +++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index e27ec9e..178296d 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -413,6 +413,7 @@ var_eq_const(VariableStatData *vardata, Oid oproid, Oid collation, AttStatsSlot sslot; bool match = false; int i; + double sumcommon = 0.0; /* * Is the constant "=" to any of the column's most common values? @@ -427,6 +428,7 @@ var_eq_const(VariableStatData *vardata, Oid oproid, Oid collation, { LOCAL_FCINFO(fcinfo, 2); FmgrInfo eqproc; + bool scan_all_mcv_values = false; fmgr_info(opfuncoid, &eqproc); @@ -446,6 +448,27 @@ var_eq_const(VariableStatData *vardata, Oid oproid, Oid collation, else fcinfo->args[0].value = constval; + if (collation != sslot.stacoll && OidIsValid(collation)) + { + pg_locale_t const_locale = NULL; + + const_locale = pg_newlocale_from_collation(collation); + if (!const_locale->deterministic) + { + pg_locale_t sta_locale = NULL; + + if (OidIsValid(sslot.stacoll)) + sta_locale = pg_newlocale_from_collation(sslot.stacoll); + /* + * Full MCV scanning is only justified and beneficial when the column + * statistics use a deterministic collation, while the comparison uses + * a nondeterministic collation. + */ + scan_all_mcv_values = !sta_locale || sta_locale->deterministic; + } + } + selec = 0.0; + for (i = 0; i < sslot.nvalues; i++) { Datum fresult; @@ -459,8 +482,17 @@ var_eq_const(VariableStatData *vardata, Oid oproid, Oid collation, if (!fcinfo->isnull && DatumGetBool(fresult)) { match = true; - break; + if (scan_all_mcv_values == false) + { + selec = sslot.numbers[i]; + break; + } + else + /* Scan all statistical entries and accumulate selectivity for matching items. */ + selec += sslot.numbers[i]; } + + sumcommon += sslot.numbers[i]; } } else @@ -469,26 +501,15 @@ var_eq_const(VariableStatData *vardata, Oid oproid, Oid collation, i = 0; /* keep compiler quiet */ } - if (match) - { - /* - * Constant is "=" to this common value. We know selectivity - * exactly (or as exactly as ANALYZE could calculate it, anyway). - */ - selec = sslot.numbers[i]; - } - else + if (match == false) { /* * Comparison is against a constant that is neither NULL nor any * of the common values. Its selectivity cannot be more than * this: */ - double sumcommon = 0.0; double otherdistinct; - for (i = 0; i < sslot.nnumbers; i++) - sumcommon += sslot.numbers[i]; selec = 1.0 - sumcommon - nullfrac; CLAMP_PROBABILITY(selec); -- 2.43.0