1313
1414#include " yb/tserver/server_main_util.h"
1515
16+ #include < algorithm>
1617#include < iostream>
18+ #include < boost/algorithm/string/trim.hpp>
19+ #include " yb/util/string_case.h"
1720
1821#if YB_ABSL_ENABLED
1922#include " absl/debugging/symbolize.h"
3134#include " yb/util/debug/trace_event.h"
3235#include " yb/util/flags.h"
3336#include " yb/util/mem_tracker.h"
37+ #include " yb/util/pg_util.h"
3438#include " yb/util/size_literals.h"
3539#include " yb/util/status.h"
3640
@@ -49,6 +53,8 @@ DECLARE_int64(memory_limit_hard_bytes);
4953DECLARE_bool (ysql_enable_auto_analyze);
5054DECLARE_bool (ysql_enable_auto_analyze_service);
5155DECLARE_bool (ysql_enable_table_mutation_counter);
56+ DECLARE_string (ysql_pg_conf_csv);
57+ DECLARE_string (ysql_yb_enable_cbo);
5258
5359namespace yb {
5460
@@ -125,40 +131,106 @@ void AdjustMemoryLimitsIfNeeded(bool is_master) {
125131 AdjustMemoryLimits (values);
126132}
127133
128- // If auto analyze service is used based on old deprecated flags,
129- // adjust new flags' values based on the deprecated flags to make auto analyze
130- // service behaves consistently.
131- // When using deprecated flags, only setting both FLAGS_ysql_enable_auto_analyze
132- // and FLAGS_ysql_enable_table_mutation_counter makes auto analyze service runable,
133- // so ysql_enable_auto_analyze is set in the following precedence order
134- // 1. Any explicit user set value for ysql_enable_auto_analyze.
135- // 2. If not set explicitly,
136- // 2.1 If ysql_enable_auto_analyze_service and ysql_enable_table_mutation_counter are set
137- // explicitly. Use their values to set value for ysql_enable_auto_analyze.
138- // ysql_enable_auto_analyze is true only if both ysql_enable_auto_analyze_service and
139- // ysql_enable_table_mutation_counter are true.
140- // 2.2 If not both of ysql_enable_auto_analyze_service and
141- // ysql_enable_table_mutation_counter are set explicity,
142- // use ysql_enable_auto_analyze default value.
134+ // Return the lower case value of a GUC set in a CSV string (FLAGS_ysql_pg_conf_csv),
135+ // accounting for the following
136+ // 1. GUC keys and values are case insensitive
137+ // 2. A GUC can be repeated multiple times, the final value is what matters
138+ // (consistent with WritePostgresConfig)
139+ std::optional<std::string> FindGUCValue (
140+ const std::string& guc_key, const std::vector<std::string>& user_configs) {
141+ std::optional<std::string> result;
142+ for (const auto & config : user_configs) {
143+ const auto lower_case_config = yb::ToLowerCase (config);
144+ if (lower_case_config.find (guc_key) == std::string::npos) {
145+ continue ;
146+ }
147+ const auto pos = lower_case_config.find (' =' );
148+ if (pos != std::string::npos) {
149+ std::string config_key = boost::trim_copy (lower_case_config.substr (0 , pos));
150+ std::string config_value = boost::trim_copy (lower_case_config.substr (pos + 1 ));
151+ if (config_key == guc_key) {
152+ result = config_value;
153+ }
154+ }
155+ }
156+ return result;
157+ }
158+
159+ // Auto analyze flag can have different defaults based on other flags like
160+ // older (deprecated) auto analyze flags or the cbo flags. In any case, an explict
161+ // user set flag value should be respected as-is.
143162void AdjustAutoAnalyzeFlagIfNeeded () {
144- // Check if the flag is explictly set.
145- if (!google::GetCommandLineFlagInfoOrDie (" ysql_enable_auto_analyze" ).is_default )
163+ // If the auto analyze flag is explictly set, do not change it.
164+ if (!google::GetCommandLineFlagInfoOrDie (" ysql_enable_auto_analyze" ).is_default ) {
165+ LOG (INFO) << " Flag: ysql_enable_auto_analyze has been set to " << FLAGS_ysql_enable_auto_analyze
166+ << " by explicit config in command line" ;
146167 return ;
147- bool old_value_of_new_flag = FLAGS_ysql_enable_auto_analyze;
148- // check if the old flags are enabled.
149- bool auto_analyze_enabled_using_old_flags
150- = FLAGS_ysql_enable_auto_analyze_service && FLAGS_ysql_enable_table_mutation_counter;
168+ }
169+
170+ // When we change ysql_yb_enable_cbo to default on, we need to update the logic here, so adding
171+ // a DCHECK to catch this situation.
172+ DCHECK (
173+ !(google::GetCommandLineFlagInfoOrDie (" ysql_yb_enable_cbo" ).is_default &&
174+ FLAGS_ysql_yb_enable_cbo == " on" ));
175+
176+ // If ysql_yb_enable_cbo was explicitly set by user, then ysql_enable_auto_analyze flag is set to
177+ // true whenever it is on. The reasoning is that CBO in legacy mode
178+ // can have more unpredictable behavior when ANALYZE is run, so we don't want to run ANALYZE
179+ // automatically.
180+ bool cbo_flag_on = false ;
181+ std::string cbo_reason = " " ;
182+ const std::vector<std::string> cbo_on_values = {" on" , " true" , " 1" , " yes" };
183+ if (!google::GetCommandLineFlagInfoOrDie (" ysql_yb_enable_cbo" ).is_default ) {
184+ if (std::find (
185+ cbo_on_values.begin (), cbo_on_values.end (),
186+ yb::ToLowerCase (FLAGS_ysql_yb_enable_cbo)) != cbo_on_values.end ()) {
187+ cbo_flag_on = true ;
188+ cbo_reason = " ysql_yb_enable_cbo flag was explicitly set by user to '" +
189+ FLAGS_ysql_yb_enable_cbo + " '" ;
190+ }
191+ } else {
192+ // If ysql_pg_conf_csv contains yb_enable_cbo=on, then ysql_enable_auto_analyze is set to true.
193+ // Note that ysql_pg_conf_csv has lower precedence than user-set ysql_yb_enable_cbo.
194+ std::vector<std::string> user_configs;
195+ std::optional<std::string> cbo_guc_value;
196+ if (!FLAGS_ysql_pg_conf_csv.empty () &&
197+ ReadCSVValues (FLAGS_ysql_pg_conf_csv, &user_configs).ok () &&
198+ (cbo_guc_value = FindGUCValue (" yb_enable_cbo" , user_configs)).has_value () &&
199+ std::find (cbo_on_values.begin (), cbo_on_values.end (), cbo_guc_value.value ()) !=
200+ cbo_on_values.end ()) {
201+ cbo_flag_on = true ;
202+ cbo_reason = " yb_enable_cbo was set to " + cbo_guc_value.value () + " in ysql_pg_conf_csv" ;
203+ }
204+ }
205+
206+ if (cbo_flag_on) {
207+ google::SetCommandLineOptionWithMode (
208+ " ysql_enable_auto_analyze" , " true" , google::SET_FLAG_IF_DEFAULT);
209+ LOG (INFO) << " Flag: ysql_yb_enable_auto_analyze was auto-set to "
210+ << FLAGS_ysql_enable_auto_analyze << " because " << cbo_reason;
211+ return ;
212+ }
213+
214+ // If ysql_enable_auto_analyze_service and ysql_enable_table_mutation_counter are set
215+ // explicitly, use their values to set value for ysql_enable_auto_analyze.
216+ // ysql_enable_auto_analyze is true only if both ysql_enable_auto_analyze_service and
217+ // ysql_enable_table_mutation_counter are true.
218+ const bool old_value_of_new_flag = FLAGS_ysql_enable_auto_analyze;
219+ const bool auto_analyze_enabled_using_old_flags =
220+ FLAGS_ysql_enable_auto_analyze_service && FLAGS_ysql_enable_table_mutation_counter;
151221 if (auto_analyze_enabled_using_old_flags) {
152- // set new flag default.
153222 google::SetCommandLineOptionWithMode (" ysql_enable_auto_analyze" , " true" ,
154223 google::SET_FLAG_IF_DEFAULT);
155224
156- LOG (INFO) << " Flag: ysql_enable_auto_analyze was auto-set to "
157- << FLAGS_ysql_enable_auto_analyze
225+ LOG (INFO) << " Flag: ysql_enable_auto_analyze was auto-set to " << FLAGS_ysql_enable_auto_analyze
158226 << " from its default value of " << old_value_of_new_flag
159- << " . Flags: ysql_enable_auto_analyze_service and "
160- << " ysql_enable_table_mutation_counter are deprecated." ;
227+ << " because it was enabled by the following deprecated flags"
228+ << " - ysql_enable_auto_analyze_service and ysql_enable_table_mutation_counter." ;
229+ return ;
161230 }
231+
232+ LOG (INFO) << " Not changing ysql_enable_auto_analyze from its default value "
233+ << FLAGS_ysql_enable_auto_analyze;
162234}
163235
164236} // anonymous namespace
0 commit comments