~percona-dev/percona-server/release-5.1.57-12.8-commit108486

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# name       : optimizer_fix.patch
# introduced : 11 or before
# maintainer : Yasufumi
#
#!!! notice !!!
# Any small change to this file in the main branch
# should be done or reviewed by the maintainer!
diff -ruN /dev/null b/patch_info/optimizer_fix.info
--- /dev/null	1970-01-01 09:00:00.000000000 +0900
+++ b/patch_info/optimizer_fix.info	2010-07-26 18:29:35.685061376 +0900
@@ -0,0 +1,8 @@
+File=optimizer_fix.patch
+Name=Unofficial optimizer fixes
+Version=1.0
+Author=Percona <info@percona.com>
+License=GPL
+Comment=
+2010-01
+Ported to 5.1.42
diff -ruN a/sql/mysql_priv.h b/sql/mysql_priv.h
--- a/sql/mysql_priv.h	2010-07-26 18:29:12.224113574 +0900
+++ b/sql/mysql_priv.h	2010-07-26 18:29:35.697144981 +0900
@@ -2110,6 +2110,7 @@
 extern ulong slave_exec_mode_options;
 extern my_bool opt_readonly, lower_case_file_system;
 extern my_bool opt_userstat_running, opt_thread_statistics;
+extern my_bool opt_optimizer_fix;
 extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
 extern my_bool opt_secure_auth;
 extern char* opt_secure_file_priv;
diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
--- a/sql/mysqld.cc	2010-07-26 18:29:12.238109757 +0900
+++ b/sql/mysqld.cc	2010-07-26 18:29:35.687113582 +0900
@@ -533,6 +533,7 @@
 #endif /* defined(ENABLED_DEBUG_SYNC) */
 my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
 my_bool opt_userstat_running= 0, opt_thread_statistics= 0;
+my_bool opt_optimizer_fix= 0;
 /*
   True if there is at least one per-hour limit for some user, so we should
   check them before each query (and possibly reset counters when hour is
@@ -5849,6 +5850,7 @@
   OPT_SLOW_QUERY_LOG_FILE,
   OPT_USERSTAT_RUNNING,
   OPT_THREAD_STATISTICS,
+  OPT_OPTIMIZER_FIX,
   OPT_USE_GLOBAL_LONG_QUERY_TIME,
   OPT_USE_GLOBAL_LOG_SLOW_CONTROL,
   OPT_SLOW_QUERY_LOG_MICROSECONDS_TIMESTAMP,
@@ -7358,6 +7360,10 @@
    "Control TABLE_STATISTICS running, when userstat_running is enabled",
    (uchar**) &opt_thread_statistics, (uchar**) &opt_thread_statistics,
    0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
+  {"optimizer_fix", OPT_OPTIMIZER_FIX,
+   "Enable unofficial optimizer fixes.",
+   (uchar**) &opt_optimizer_fix, (uchar**) &opt_optimizer_fix,
+   0, GET_BOOL, NO_ARG, 1, 0, 1, 0, 1, 0},
   {"binlog-direct-non-transactional-updates", OPT_BINLOG_DIRECT_NON_TRANS_UPDATE,
    "Causes updates to non-transactional engines using statement format to be "
    "written directly to binary log. Before using this option, make sure that "
diff -ruN a/sql/opt_range.cc b/sql/opt_range.cc
--- a/sql/opt_range.cc	2010-07-09 21:34:57.000000000 +0900
+++ b/sql/opt_range.cc	2010-07-26 18:29:35.711113511 +0900
@@ -695,7 +695,7 @@
 static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
                                        bool index_read_must_be_used,
                                        bool update_tbl_stats,
-                                       double read_time);
+                                       double read_time, ha_rows *estimated_records);
 static
 TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
                                           double read_time,
@@ -2200,6 +2200,7 @@
 				  ha_rows limit, bool force_quick_range)
 {
   uint idx;
+  ha_rows estimated_records=0;
   double scan_time;
   DBUG_ENTER("SQL_SELECT::test_quick_select");
   DBUG_PRINT("enter",("keys_to_use: %lu  prev_tables: %lu  const_tables: %lu",
@@ -2370,12 +2371,17 @@
 
         /* Get best 'range' plan and prepare data for making other plans */
         if ((range_trp= get_key_scans_params(&param, tree, FALSE, TRUE,
-                                             best_read_time)))
+                                             best_read_time, &estimated_records)))
         {
           best_trp= range_trp;
           best_read_time= best_trp->read_cost;
         }
 
+        if (opt_optimizer_fix && estimated_records)
+        {
+          records = estimated_records;
+        }
+
         /*
           Simultaneous key scans and row deletes on several handler
           objects are not allowed so don't use ROR-intersection for
@@ -3726,7 +3732,7 @@
   {
     DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map,
                                         "tree in SEL_IMERGE"););
-    if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time)))
+    if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time, NULL)))
     {
       /*
         One of index scans in this index_merge is more expensive than entire
@@ -4829,11 +4835,12 @@
 static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
                                        bool index_read_must_be_used, 
                                        bool update_tbl_stats,
-                                       double read_time)
+                                       double read_time, ha_rows *estimated_records)
 {
   int idx;
   SEL_ARG **key,**end, **key_to_read= NULL;
   ha_rows UNINIT_VAR(best_records);              /* protected by key_to_read */
+  ha_rows min_records= HA_POS_ERROR;
   TRP_RANGE* read_plan= NULL;
   bool pk_is_clustered= param->table->file->primary_key_is_clustered();
   DBUG_ENTER("get_key_scans_params");
@@ -4904,6 +4911,11 @@
         key_to_read=  key;
       }
 
+      if (estimated_records && found_records
+          && min_records > found_records)
+      {
+        min_records = found_records;
+      }
     }
   }
 
@@ -4926,6 +4938,12 @@
   else
     DBUG_PRINT("info", ("No 'range' table read plan found"));
 
+  /* minimum number of records (not 0) as estimated number of records */
+  if (estimated_records && min_records != HA_POS_ERROR)
+  {
+    *estimated_records = min_records;
+  }
+
   DBUG_RETURN(read_plan);
 }
 
diff -ruN a/sql/set_var.cc b/sql/set_var.cc
--- a/sql/set_var.cc	2010-07-26 18:29:12.250113584 +0900
+++ b/sql/set_var.cc	2010-07-26 18:29:35.724113196 +0900
@@ -571,6 +571,8 @@
 						     &opt_userstat_running);
 static sys_var_bool_ptr		sys_thread_statistics(&vars, "thread_statistics",
 						      &opt_thread_statistics);
+static sys_var_bool_ptr		sys_optimizer_fix(&vars, "optimizer_fix",
+						  &opt_optimizer_fix);
 static sys_var_thd_ulong	sys_read_rnd_buff_size(&vars, "read_rnd_buffer_size",
 					       &SV::read_rnd_buff_size);
 static sys_var_thd_ulong	sys_div_precincrement(&vars, "div_precision_increment",
diff -ruN a/sql/sql_select.cc b/sql/sql_select.cc
--- a/sql/sql_select.cc	2010-07-26 18:23:40.015145156 +0900
+++ b/sql/sql_select.cc	2010-07-26 18:29:35.743144611 +0900
@@ -2601,6 +2601,11 @@
       table->reginfo.impossible_range=1;
       DBUG_RETURN(0);
     }
+    if (opt_optimizer_fix && error == 0)
+    {
+      /* quick select is not effective. but the estimated value is used. */
+      DBUG_RETURN(select->records);
+    }
     DBUG_PRINT("warning",("Couldn't use record count on const keypart"));
   }
   DBUG_RETURN(HA_POS_ERROR);			/* This shouldn't happend */