Skip to content

Commit e57bfc1

Browse files
MDEV-32732 Support DESC indexes in loose scan optimization
Extend loose index scan to support descending indexes. This is achieved by removing a block skipping creating loose index scan plan for descending index, as well as generalising the execution of such plans. The generalisation applies to all levels looking for min/max in loose index scan. In the highest level (get_next), generalise min and max to first and last, so that it still proceeds in the direction agreeing with the index parity. In the lower levels, combine next_min and next_max methods into next_min_max, and combine next_min_in_range and next_max_in_range into next_min_max_in_range. This retains existing logic of these functions and reduces code duplication, while allowing handling of all four combinations (min, max) x (asc index, desc index).
1 parent 689bed1 commit e57bfc1

File tree

6 files changed

+610
-290
lines changed

6 files changed

+610
-290
lines changed

mysql-test/main/desc_index_range.result

+259-3
Original file line numberDiff line numberDiff line change
@@ -146,16 +146,19 @@ CREATE TABLE t1 (p int NOT NULL, a int NOT NULL, PRIMARY KEY (p,a desc));
146146
insert into t1 select 2,seq from seq_0_to_1000;
147147
EXPLAIN select MIN(a) from t1 where p = 2 group by p;
148148
id select_type table type possible_keys key key_len ref rows Extra
149-
1 SIMPLE t1 ref PRIMARY PRIMARY 4 const 1000 Using index
149+
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 Using where; Using index for group-by
150150
select json_detailed(json_extract(trace, '$**.potential_group_range_indexes')) as jd
151151
from information_schema.optimizer_trace;
152152
jd
153153
[
154154
[
155155
{
156156
"index": "PRIMARY",
157-
"usable": false,
158-
"cause": "Reverse-ordered (not supported yet)"
157+
"covering": true,
158+
"ranges":
159+
["(2) <= (p) <= (2)"],
160+
"rows": 1,
161+
"cost": 0.000838227
159162
}
160163
]
161164
]
@@ -199,3 +202,256 @@ select * from t1 where b = 255 AND a IS NULL;
199202
pk a b
200203
10000 NULL 255
201204
drop table t1;
205+
#
206+
# MDEV-32732 Support DESC indexes in loose scan optimization
207+
#
208+
create table t1 (a int, c int, key (a, c desc));
209+
insert into t1 values (1, 9), (1, 6), (1, 3);
210+
explain SELECT MAX(c), MIN(c) FROM t1 group by a;
211+
id select_type table type possible_keys key key_len ref rows Extra
212+
1 SIMPLE t1 range NULL a 10 NULL 3 Using index for group-by
213+
SELECT MAX(c), MIN(c) FROM t1 group by a;
214+
MAX(c) MIN(c)
215+
9 3
216+
drop table t1;
217+
create table t1 (a int, b int, c int, key (a desc, b, c desc));
218+
insert into t1 values (1, 2, 9), (1, 2, 6), (2, 1, 3), (2, 1, 12);
219+
explain SELECT a, b, MAX(c), MIN(c) FROM t1 group by a, b;
220+
id select_type table type possible_keys key key_len ref rows Extra
221+
1 SIMPLE t1 range NULL a 15 NULL 4 Using index for group-by; Using temporary; Using filesort
222+
SELECT a, b, MAX(c), MIN(c) FROM t1 group by a, b;
223+
a b MAX(c) MIN(c)
224+
1 2 9 6
225+
2 1 12 3
226+
drop table t1;
227+
CREATE TABLE t1 (a int, b int, KEY (a, b desc));
228+
insert into t1 values (1, 23), (3, 45), (1, 11), (3, 88), (3, 70), (4, NULL), (1, 14), (4, NULL);
229+
SELECT MIN(b) FROM t1 GROUP BY a;
230+
MIN(b)
231+
11
232+
45
233+
NULL
234+
SELECT MIN(b) FROM t1 WHERE b < 68 GROUP BY a;
235+
MIN(b)
236+
11
237+
45
238+
SELECT MIN(b) FROM t1 WHERE b > 13 GROUP BY a;
239+
MIN(b)
240+
14
241+
45
242+
SELECT MIN(b) FROM t1 WHERE b > 13 AND b < 68 GROUP BY a;
243+
MIN(b)
244+
14
245+
45
246+
SELECT MIN(b) FROM t1 WHERE b >= 14 AND b < 68 GROUP BY a;
247+
MIN(b)
248+
14
249+
45
250+
SELECT MIN(b) FROM t1 WHERE b > 14 AND b < 68 GROUP BY a;
251+
MIN(b)
252+
23
253+
45
254+
SELECT MIN(b) FROM t1 WHERE (b > 47 AND b < 91) OR (b > 11 AND b < 30) GROUP BY a;
255+
MIN(b)
256+
14
257+
70
258+
SELECT MIN(b) FROM t1 WHERE (b > 13 AND b < 68) OR (b IS NULL) GROUP BY a;
259+
MIN(b)
260+
14
261+
45
262+
NULL
263+
SELECT MIN(b) FROM t1 WHERE (b > 13 AND b < 68) OR (b = 100) GROUP BY a;
264+
MIN(b)
265+
14
266+
45
267+
SELECT MAX(b) FROM t1 GROUP BY a;
268+
MAX(b)
269+
23
270+
88
271+
NULL
272+
SELECT MAX(b) FROM t1 WHERE b < 68 GROUP BY a;
273+
MAX(b)
274+
23
275+
45
276+
SELECT MAX(b) FROM t1 WHERE b > 13 GROUP BY a;
277+
MAX(b)
278+
23
279+
88
280+
SELECT MAX(b) FROM t1 WHERE b > 13 AND b < 68 GROUP BY a;
281+
MAX(b)
282+
23
283+
45
284+
SELECT MAX(b) FROM t1 WHERE b >= 14 AND b < 68 GROUP BY a;
285+
MAX(b)
286+
23
287+
45
288+
SELECT MAX(b) FROM t1 WHERE (b > 47 AND b < 91) OR (b > 11 AND b < 30) GROUP BY a;
289+
MAX(b)
290+
23
291+
88
292+
SELECT MAX(b) FROM t1 WHERE (b > 13 AND b < 68) OR (b IS NULL) GROUP BY a;
293+
MAX(b)
294+
23
295+
45
296+
NULL
297+
SELECT MAX(b) FROM t1 WHERE (b > 13 AND b < 68) OR (b = 100) GROUP BY a;
298+
MAX(b)
299+
23
300+
45
301+
insert into t1 values (4, 8);
302+
SELECT MIN(b) FROM t1 GROUP BY a;
303+
MIN(b)
304+
11
305+
45
306+
8
307+
SELECT MIN(b) FROM t1 WHERE b < 68 GROUP BY a;
308+
MIN(b)
309+
11
310+
45
311+
8
312+
SELECT MIN(b) FROM t1 WHERE b > 13 GROUP BY a;
313+
MIN(b)
314+
14
315+
45
316+
SELECT MIN(b) FROM t1 WHERE b > 13 AND b < 68 GROUP BY a;
317+
MIN(b)
318+
14
319+
45
320+
SELECT MIN(b) FROM t1 WHERE b >= 14 AND b < 68 GROUP BY a;
321+
MIN(b)
322+
14
323+
45
324+
SELECT MIN(b) FROM t1 WHERE (b > 47 AND b < 91) OR (b > 11 AND b < 30) GROUP BY a;
325+
MIN(b)
326+
14
327+
70
328+
SELECT MIN(b) FROM t1 WHERE (b > 13 AND b < 68) OR (b IS NULL) GROUP BY a;
329+
MIN(b)
330+
14
331+
45
332+
NULL
333+
SELECT MIN(b) FROM t1 WHERE (b > 13 AND b < 68) OR (b = 100) GROUP BY a;
334+
MIN(b)
335+
14
336+
45
337+
SELECT MAX(b) FROM t1 GROUP BY a;
338+
MAX(b)
339+
23
340+
88
341+
8
342+
SELECT MAX(b) FROM t1 WHERE b < 68 GROUP BY a;
343+
MAX(b)
344+
23
345+
45
346+
8
347+
SELECT MAX(b) FROM t1 WHERE b > 13 GROUP BY a;
348+
MAX(b)
349+
23
350+
88
351+
SELECT MAX(b) FROM t1 WHERE b > 13 AND b < 68 GROUP BY a;
352+
MAX(b)
353+
23
354+
45
355+
SELECT MAX(b) FROM t1 WHERE b >= 14 AND b < 68 GROUP BY a;
356+
MAX(b)
357+
23
358+
45
359+
SELECT MAX(b) FROM t1 WHERE (b > 47 AND b < 91) OR (b > 11 AND b < 30) GROUP BY a;
360+
MAX(b)
361+
23
362+
88
363+
SELECT MAX(b) FROM t1 WHERE (b > 13 AND b < 68) OR (b IS NULL) GROUP BY a;
364+
MAX(b)
365+
23
366+
45
367+
NULL
368+
SELECT MAX(b) FROM t1 WHERE (b > 13 AND b < 68) OR (b = 100) GROUP BY a;
369+
MAX(b)
370+
23
371+
45
372+
drop table t1;
373+
create table t1(c1 int, c2 int, c3 int, c4 int, key (c1 desc, c2 desc, c3 desc));
374+
insert into t1 values (1, 2, 9, 2), (3, 2, 6, 9), (1, 2, 6, 9), (4, 1, 3, 38), (4, 1, 12, 12);
375+
select distinct c1 from t1;
376+
c1
377+
4
378+
3
379+
1
380+
select distinct c1 from t1 where c2 = 2;
381+
c1
382+
3
383+
1
384+
select c1 from t1 group by c1;
385+
c1
386+
1
387+
3
388+
4
389+
select distinct c1, c2 from t1;
390+
c1 c2
391+
4 1
392+
3 2
393+
1 2
394+
select c1, c2 from t1 group by c1, c2;
395+
c1 c2
396+
1 2
397+
3 2
398+
4 1
399+
SELECT c1, MIN(c2) FROM t1 GROUP BY c1;
400+
c1 MIN(c2)
401+
1 2
402+
3 2
403+
4 1
404+
SELECT c1, c2, min(c3), max(c3) FROM t1 WHERE c2 = 2 GROUP BY c1;
405+
c1 c2 min(c3) max(c3)
406+
1 2 6 9
407+
3 2 6 6
408+
SELECT c1, c2 FROM t1 WHERE c1 < 3 GROUP BY c1, c2;
409+
c1 c2
410+
1 2
411+
SELECT MAX(c3), MIN(c3), c1, c2 FROM t1 WHERE c2 > 1 GROUP BY c1, c2;
412+
MAX(c3) MIN(c3) c1 c2
413+
9 6 1 2
414+
6 6 3 2
415+
SELECT c2 FROM t1 WHERE c1 < 3 GROUP BY c1, c2;
416+
c2
417+
2
418+
SELECT c1, c2 FROM t1 WHERE c3 = 6 GROUP BY c1, c2;
419+
c1 c2
420+
1 2
421+
3 2
422+
SELECT c1, c3 FROM t1 WHERE c3 = 6 GROUP BY c1, c2;
423+
c1 c3
424+
1 6
425+
3 6
426+
insert into t1 values (1, 3, 3, 4);
427+
SELECT c1, c2, min(c3), max(c3) FROM t1 WHERE c2 = 2 GROUP BY c1;
428+
c1 c2 min(c3) max(c3)
429+
1 2 6 9
430+
3 2 6 6
431+
insert into t1 values (1, 4, NULL, 4);
432+
SELECT c1, c2, min(c3), max(c3) FROM t1 WHERE c2 = 2 GROUP BY c1;
433+
c1 c2 min(c3) max(c3)
434+
1 2 6 9
435+
3 2 6 6
436+
drop table t1;
437+
create table t20 (
438+
kp1 int,
439+
kp2 int,
440+
index (kp1 desc, kp2 desc)
441+
);
442+
insert into t20 select A.seq, B.seq from seq_1_to_10 A, seq_1_to_10 B;
443+
insert into t20 values (1, NULL);
444+
insert into t20 values (10, NULL);
445+
select min(kp2) from t20 where kp2=3 or kp2=5 or kp2 is null group by kp1;
446+
min(kp2)
447+
3
448+
3
449+
3
450+
3
451+
3
452+
3
453+
3
454+
3
455+
3
456+
3
457+
drop table t20;

0 commit comments

Comments
 (0)