1
# name : optimizer_fix.patch
2
# introduced : 11 or before
3
# maintainer : Yasufumi
6
# Any small change to this file in the main branch
7
# should be done or reviewed by the maintainer!
9
+++ b/patch_info/optimizer_fix.info
11
+File=optimizer_fix.patch
12
+Name=Unofficial optimizer fixes
14
+Author=Percona <info@percona.com>
19
--- a/sql/mysql_priv.h
20
+++ b/sql/mysql_priv.h
22
extern ulong slave_exec_mode_options;
23
extern my_bool opt_readonly, lower_case_file_system;
24
extern my_bool opt_userstat_running, opt_thread_statistics;
25
+extern my_bool opt_optimizer_fix;
26
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
27
extern my_bool opt_secure_auth;
28
extern char* opt_secure_file_priv;
32
#endif /* defined(ENABLED_DEBUG_SYNC) */
33
my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
34
my_bool opt_userstat_running= 0, opt_thread_statistics= 0;
35
+my_bool opt_optimizer_fix= 0;
37
True if there is at least one per-hour limit for some user, so we should
38
check them before each query (and possibly reset counters when hour is
40
OPT_SLOW_QUERY_LOG_FILE,
42
OPT_THREAD_STATISTICS,
44
OPT_USE_GLOBAL_LONG_QUERY_TIME,
45
OPT_USE_GLOBAL_LOG_SLOW_CONTROL,
46
OPT_SLOW_QUERY_LOG_MICROSECONDS_TIMESTAMP,
47
@@ -7381,6 +7383,10 @@
48
"Control TABLE_STATISTICS running, when userstat_running is enabled",
49
(uchar**) &opt_thread_statistics, (uchar**) &opt_thread_statistics,
50
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
51
+ {"optimizer_fix", OPT_OPTIMIZER_FIX,
52
+ "Enable unofficial optimizer fixes.",
53
+ (uchar**) &opt_optimizer_fix, (uchar**) &opt_optimizer_fix,
54
+ 0, GET_BOOL, NO_ARG, 1, 0, 1, 0, 1, 0},
55
{"binlog-direct-non-transactional-updates", OPT_BINLOG_DIRECT_NON_TRANS_UPDATE,
56
"Causes updates to non-transactional engines using statement format to be "
57
"written directly to binary log. Before using this option, make sure that "
58
--- a/sql/opt_range.cc
59
+++ b/sql/opt_range.cc
61
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
62
bool index_read_must_be_used,
63
bool update_tbl_stats,
65
+ double read_time, ha_rows *estimated_records);
67
TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
70
ha_rows limit, bool force_quick_range)
73
+ ha_rows estimated_records=0;
75
DBUG_ENTER("SQL_SELECT::test_quick_select");
76
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
77
@@ -2370,12 +2371,17 @@
79
/* Get best 'range' plan and prepare data for making other plans */
80
if ((range_trp= get_key_scans_params(¶m, tree, FALSE, TRUE,
82
+ best_read_time, &estimated_records)))
85
best_read_time= best_trp->read_cost;
88
+ if (opt_optimizer_fix && estimated_records)
90
+ records = estimated_records;
94
Simultaneous key scans and row deletes on several handler
95
objects are not allowed so don't use ROR-intersection for
98
DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map,
99
"tree in SEL_IMERGE"););
100
- if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time)))
101
+ if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time, NULL)))
104
One of index scans in this index_merge is more expensive than entire
105
@@ -4829,11 +4835,12 @@
106
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
107
bool index_read_must_be_used,
108
bool update_tbl_stats,
110
+ double read_time, ha_rows *estimated_records)
113
SEL_ARG **key,**end, **key_to_read= NULL;
114
ha_rows UNINIT_VAR(best_records); /* protected by key_to_read */
115
+ ha_rows min_records= HA_POS_ERROR;
116
TRP_RANGE* read_plan= NULL;
117
bool pk_is_clustered= param->table->file->primary_key_is_clustered();
118
DBUG_ENTER("get_key_scans_params");
119
@@ -4904,6 +4911,11 @@
123
+ if (estimated_records && found_records
124
+ && min_records > found_records)
126
+ min_records = found_records;
131
@@ -4926,6 +4938,12 @@
133
DBUG_PRINT("info", ("No 'range' table read plan found"));
135
+ /* minimum number of records (not 0) as estimated number of records */
136
+ if (estimated_records && min_records != HA_POS_ERROR)
138
+ *estimated_records = min_records;
141
DBUG_RETURN(read_plan);
147
&opt_userstat_running);
148
static sys_var_bool_ptr sys_thread_statistics(&vars, "thread_statistics",
149
&opt_thread_statistics);
150
+static sys_var_bool_ptr sys_optimizer_fix(&vars, "optimizer_fix",
151
+ &opt_optimizer_fix);
152
static sys_var_thd_ulong sys_read_rnd_buff_size(&vars, "read_rnd_buffer_size",
153
&SV::read_rnd_buff_size);
154
static sys_var_thd_ulong sys_div_precincrement(&vars, "div_precision_increment",
155
--- a/sql/sql_select.cc
156
+++ b/sql/sql_select.cc
157
@@ -2605,6 +2605,11 @@
158
table->reginfo.impossible_range=1;
161
+ if (opt_optimizer_fix && error == 0)
163
+ /* quick select is not effective. but the estimated value is used. */
164
+ DBUG_RETURN(select->records);
166
DBUG_PRINT("warning",("Couldn't use record count on const keypart"));
168
DBUG_RETURN(HA_POS_ERROR); /* This shouldn't happend */