MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
range.inc
1 # Test for optimizer tracing of range analysis
2 
3 --source include/have_optimizer_trace.inc
4 # InnoDB page size influences cost => makes trace vary.
5 --source include/have_innodb_16k.inc
6 
7 SET optimizer_trace_max_mem_size=1048576; # 1MB
8 SET end_markers_in_json=on;
9 SET optimizer_trace="enabled=on,one_line=off";
10 
11 CREATE TABLE t1
12 (
13  key1 INT NOT NULL,
14  INDEX i1(key1)
15 );
16 
17 --echo Inserting 1024 records into t1
18 
19 --disable_query_log
20 INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8);
21 
22 let $1=7;
23 set @d=8;
24 while ($1)
25 {
26  EVAL INSERT INTO t1 SELECT key1+@d FROM t1;
27  EVAL SET @d=@d*2;
28  DEC $1;
29 }
30 --enable_query_log
31 
32 ALTER TABLE t1 ADD key2 INT NOT NULL, ADD INDEX i2(key2);
33 ALTER TABLE t1 ADD key3 INT NOT NULL, ADD INDEX i3(key3);
34 ALTER TABLE t1 ADD key4 INT NOT NULL, ADD INDEX i4(key4);
35 ALTER TABLE t1 ADD key5 INT NOT NULL, ADD INDEX i5(key5);
36 ALTER TABLE t1 ADD key6 INT NOT NULL, ADD INDEX i6(key6);
37 ALTER TABLE t1 ADD key7 INT NOT NULL, ADD INDEX i7(key7);
38 ALTER TABLE t1 ADD key8 INT NOT NULL, ADD INDEX i8(key8);
39 
40 UPDATE t1 SET
41  key2=key1,
42  key3=key1,
43  key4=key1,
44  key5=key1,
45  key6=key1,
46  key7=key1,
47  key8=1024-key1;
48 
49 CREATE TABLE t2 (
50  key1a INT NOT NULL,
51  key1b INT NOT NULL,
52  key2 INT NOT NULL,
53  key2_1 INT NOT NULL,
54  key2_2 INT NOT NULL,
55  key3 INT NOT NULL,
56  primary key i1a (key1a, key1b),
57  INDEX i1b (key1b, key1a),
58  INDEX i2_1(key2, key2_1),
59  INDEX i2_2(key2, key2_1)
60 );
61 
62 INSERT INTO t2 SELECT key1,key1,key1 div 10, key1 % 10, key1 % 10, key1 FROM t1;
63 
64 # multiple ranges on one key
65 --echo
66 EXPLAIN SELECT * FROM t1 WHERE key2 < 5 OR key2 > 1020;
67 --echo
68 SELECT * FROM information_schema.OPTIMIZER_TRACE;
69 
70 # multiple ranges on one key, turn off range_optimizer tracing
71 set @@optimizer_trace_features="range_optimizer=off";
72 --echo
73 EXPLAIN SELECT * FROM t1 WHERE key2 < 5 OR key2 > 1020;
74 --echo
75 SELECT * FROM information_schema.OPTIMIZER_TRACE;
76 set @@optimizer_trace_features="range_optimizer=on";
77 
78 
79 # index merge
80 --echo
81 EXPLAIN SELECT * FROM t1 WHERE key1 < 3 OR key2 > 1020;
82 --echo
83 SELECT * FROM information_schema.OPTIMIZER_TRACE;
84 
85 # group without range
86 --echo
87 EXPLAIN SELECT key2, MIN(key2_1) FROM t2 GROUP BY key2;
88 --echo
89 SELECT * FROM information_schema.OPTIMIZER_TRACE;
90 
91 # distinct - group quick select without grouping attribute
92 EXPLAIN SELECT DISTINCT key2 FROM t2;
93 --echo
94 SELECT * FROM information_schema.OPTIMIZER_TRACE;
95 
96 # group with range
97 --echo
98 EXPLAIN SELECT key2, MIN(key2_1) FROM t2
99 WHERE key2 = 5 or key2 = 4 or key2 = 3 or key2 = 2 or key2 = 1
100 GROUP BY key2;
101 --echo
102 SELECT * FROM information_schema.OPTIMIZER_TRACE;
103 
104 #intersect
105 --echo
106 EXPLAIN SELECT * FROM t2 WHERE key2 = 1 AND (key2_1 = 1 OR key3 = 5);
107 --echo
108 SELECT * FROM information_schema.OPTIMIZER_TRACE;
109 
110 # union
111 --echo
112 EXPLAIN SELECT * FROM t1 WHERE key2=10 OR key3=3 OR key4 <=> null;
113 --echo
114 SELECT * FROM information_schema.OPTIMIZER_TRACE;
115 
116 # range_scan_possible=false
117 --echo
118 EXPLAIN SELECT * FROM t2 WHERE key2_1 < 79 OR key2 = 2;
119 --echo
120 SELECT * FROM information_schema.OPTIMIZER_TRACE;
121 
122 # Multiple key parts in same index
123 --echo
124 EXPLAIN SELECT * FROM t2 WHERE key1a = 5 and key1b < 10;
125 --echo
126 SELECT * FROM information_schema.OPTIMIZER_TRACE;
127 
128 # Multiple ranges on key parts in same index
129 --echo
130 EXPLAIN SELECT * FROM t2 WHERE (key1a = 5 and key1b < 10 and key1b > 2) or
131  (key1a = 4 and key1b < 7 and key1b > 3);
132 --echo
133 SELECT * FROM information_schema.OPTIMIZER_TRACE;
134 
135 # Multiple ranges on key parts in same index
136 --echo
137 EXPLAIN SELECT * FROM t2 WHERE (key1b < 10 and key1b > 7) and
138  (key1a = 4 or key1a = 5);
139 --echo
140 SELECT * FROM information_schema.OPTIMIZER_TRACE;
141 
142 # more_expensive_than_table_scan
143 --echo
144 EXPLAIN SELECT * FROM t1 WHERE (key1 > 1 OR key2 > 2);
145 --echo
146 SELECT * FROM information_schema.OPTIMIZER_TRACE;
147 
148 # Range analysis on straight join
149 --echo
150 EXPLAIN SELECT STRAIGHT_JOIN * FROM t1, t2
151  WHERE t1.key1=t2.key1a AND t1.key2 > 1020;
152 --echo
153 SELECT * FROM information_schema.OPTIMIZER_TRACE;
154 
155 DROP TABLE t1,t2;
156 
157 CREATE TABLE t1 (
158  cola char(3) not null,
159  colb char(3) not null,
160  filler char(200),
161  key(cola),
162  key(colb)
163 );
164 INSERT INTO t1 VALUES ('foo','bar', 'ZZ'),('fuz','baz', 'ZZ');
165 
166 --echo Inserting records
167 --disable_query_log
168 let $1=9;
169 while ($1)
170 {
171  eval INSERT INTO t1 SELECT * FROM t1 WHERE cola = 'foo';
172  dec $1;
173 }
174 LET $1=13;
175 WHILE ($1)
176 {
177  eval INSERT INTO t1 SELECT * FROM t1 WHERE cola <> 'foo';
178  dec $1;
179 }
180 
181 --enable_query_log
182 
183 --echo
184 # Index roworder intersect
185 EXPLAIN SELECT * FROM t1 WHERE cola = 'foo' AND colb = 'bar';
186 --echo
187 SELECT * FROM information_schema.OPTIMIZER_TRACE;
188 
189 --echo
190 # Range with escaped character should be printed escaped
191 EXPLAIN SELECT * FROM t1 WHERE cola = 'f\no';
192 --echo
193 SELECT * FROM information_schema.OPTIMIZER_TRACE;
194 
195 DROP TABLE t1;
196 
197 # Test that range optimization is not shown for every outer record
198 # when there is a dynamic range.
199 CREATE TABLE t1(c INT);
200 INSERT INTO t1 VALUES (),();
201 CREATE TABLE t2 (b INT, KEY(b));
202 INSERT INTO t2 VALUES (),(),();
203 
204 # First, enable dynamic range optimization tracing
205 SET optimizer_trace_features="greedy_search=off,dynamic_range=on";
206 EXPLAIN SELECT 1 FROM
207  (SELECT 1 FROM t2,t1 WHERE b < c GROUP BY 1 LIMIT 1) AS d2;
208 --echo
209 SELECT * FROM information_schema.OPTIMIZER_TRACE;
210 --echo
211 
212 # Second, disable dynamic range optimization tracing
213 SET optimizer_trace_features="greedy_search=off,dynamic_range=off";
214 EXPLAIN SELECT 1 FROM
215  (SELECT 1 FROM t2,t1 WHERE b < c GROUP BY 1 LIMIT 1) AS d2;
216 --echo
217 SELECT * FROM information_schema.OPTIMIZER_TRACE;
218 --echo
219 
220 DROP TABLE t1,t2;
221 
222 SET optimizer_trace_features=default;
223 
224 # Range analysis in test_if_skip_sort_order
225 # (records_estimation_for_index_ordering)
226 CREATE TABLE t1 (
227  i1 int,
228  i2 int,
229  c char(1),
230  KEY k1 (i1),
231  KEY k2 (i1, i2)
232 );
233 INSERT INTO t1 VALUES (0,1,'2'),(3,2,'1');
234 
235 EXPLAIN SELECT * FROM t1 WHERE i1 > '2' ORDER BY i1, i2;
236 --echo
237 SELECT * FROM information_schema.OPTIMIZER_TRACE;
238 --echo
239 
240 EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE i1 >= '1' ORDER BY i1 DESC;
241 --echo
242 SELECT * FROM information_schema.OPTIMIZER_TRACE;
243 --echo
244 
245 DROP TABLE t1;
246 
247 # Analyze whether to use covering roworder intersect
248 CREATE TABLE t1 (
249  pk INT PRIMARY KEY,
250  i1 INT,
251  i2 INT,
252  v varchar(1),
253  INDEX i1_idx (i1),
254  INDEX v_idx (v,i1)
255 ) ENGINE=InnoDB;
256 
257 INSERT INTO t1 VALUES (1, 1, 9,'a'), (2, 2, 8,'b'), (3, 3, 7,'c'),
258  (4, 4, 6,'d'), (5, 5, 5,'e');
259 
260 -- disable_query_log
261 -- disable_result_log
262 ANALYZE TABLE t1;
263 -- enable_result_log
264 -- enable_query_log
265 
266 --echo
267 --echo # Covering ROR intersect not chosen: only one scan used
268 EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AND v = 'a' AND pk < 3;
269 --echo
270 SELECT * FROM information_schema.OPTIMIZER_TRACE;
271 
272 DROP INDEX i1_idx ON t1;
273 CREATE INDEX i1_i2_idx ON t1 (i2,i1);
274 
275 ANALYZE TABLE t1;
276 
277 --echo
278 --echo # Covering ROR intersect not chosen: cost
279 EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AND i2 = 1 AND v = 'a' AND pk < 3;
280 --echo
281 SELECT * FROM information_schema.OPTIMIZER_TRACE;
282 
283 # Todo: make a test case that chooses ROR intersect
284 
285 --echo
286 DROP TABLE t1;
287 
288 # Optimizer first decides to use ref, then changes mind to use range instead
289 CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b), KEY b (b)) ENGINE=InnoDB STATS_PERSISTENT=0;
290 INSERT INTO t1 VALUES (1,1),(1,2),(1,0),(1,3);
291 
292 # -- disable_query_log
293 # -- disable_result_log
294 # ANALYZE TABLE t1;
295 # -- enable_result_log
296 # -- enable_query_log
297 
298 --echo
299 --echo # Test trace for "access_type_changed 'ref' to 'range'"
300 EXPLAIN SELECT MAX(b), a FROM t1 WHERE b < 2 AND a = 1 GROUP BY a;
301 --echo
302 SELECT * FROM information_schema.OPTIMIZER_TRACE;
303 
304 --echo
305 drop table t1;
306 
307 --echo #
308 --echo # Tracing of when test_if_skip_sort_order() switches to another
309 --echo # index and we abandon ICP,
310 --echo # see "disabling_pushed_condition_on_old_index" in trace.
311 --echo #
312 
313 CREATE TABLE t1 (
314  c1 VARCHAR(2) NOT NULL,
315  i1 INTEGER NOT NULL,
316  c2 VARCHAR(2) NOT NULL,
317  KEY k1 (c1),
318  KEY k2 (c1, i1)
319 );
320 
321 INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1');
322 
323 EXPLAIN SELECT * FROM t1 WHERE c1 = '1' ORDER BY i1;
324 
325 SELECT * FROM information_schema.OPTIMIZER_TRACE;
326 
327 DROP TABLE t1;