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 */