Skip to content

Commit 7e42337

Browse files
MDEV-34413 Index Condition Pushdown for reverse ordered scans
Allows index condition pushdown for reverse ordered scans, a previously disabled feature due to poor performance. This patch adds a new API to the handler class called set_end_range which allows callers to tell the handler what the end of the index range will be when scanning. Combined with a pushed index condition, the handler can scan the index efficiently and not read beyond the end of the given range. When checking if the pushed index condition matches, the handler will also check if scanning has reached the end of the provided range and stop if so. If we instead only enabled ICP for reverse ordered scans without also calling this new API, then the handler would perform unnecessary index condition checks. In fact this would continue until the end of the index is reached. These changes are agnostic of storage engine. That is, any storage engine that supports index condition pushdown will inhereit this new behavior as it is implemented in the SQL and storage engine API layers. The partitioned tables storage meta-engine (ha_partition) adds an override of set_end_range which recursively calls set_end_range on its child storage engine (handler) implementations. This commit updates the test made in an earlier commit to show that ICP matches happen for the reverse ordered case. This patch is based on changes written by Olav Sandstaa in MySQL commit da1d92fd46071cd86de61058b6ea39fd9affcd87
1 parent 261d552 commit 7e42337

20 files changed

+218
-72
lines changed

mysql-test/main/mdev-34413-icp-reverse-order.result

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ a b c
1919
10 10 10
2020
explain select * from t10 force index(a) where a between 10 and 20 and b+1 <3333 order by a desc, b desc;
2121
id select_type table type possible_keys key key_len ref rows Extra
22-
1 SIMPLE t10 range a a 5 NULL 11 Using where
22+
1 SIMPLE t10 range a a 5 NULL 11 Using index condition
2323
flush status;
2424
select * from t10 force index(a) where a between 10 and 20 and b+1 <3333 order by a desc, b desc;
2525
a b c
@@ -36,8 +36,8 @@ a b c
3636
10 10 10
3737
SELECT * FROM information_schema.SESSION_STATUS WHERE VARIABLE_NAME LIKE '%icp%';
3838
VARIABLE_NAME VARIABLE_VALUE
39-
HANDLER_ICP_ATTEMPTS0
40-
HANDLER_ICP_MATCH0
39+
HANDLER_ICP_ATTEMPTS11
40+
HANDLER_ICP_MATCH11
4141
select * from t10 force index(a) where a between 10 and 20 and b+1 <3333 order by a asc, b asc;
4242
a b c
4343
10 10 10
@@ -77,15 +77,15 @@ a b c
7777
10 10 10
7878
explain select * from t10 force index(a) where a=10 and b+1 <3333 order by a desc, b desc;
7979
id select_type table type possible_keys key key_len ref rows Extra
80-
1 SIMPLE t10 ref a a 5 const 1 Using where
80+
1 SIMPLE t10 ref a a 5 const 1 Using index condition; Using where
8181
flush status;
8282
select * from t10 force index(a) where a=10 and b+1 <3333 order by a desc, b desc;
8383
a b c
8484
10 10 10
8585
SELECT * FROM information_schema.SESSION_STATUS WHERE VARIABLE_NAME LIKE '%icp%';
8686
VARIABLE_NAME VARIABLE_VALUE
87-
HANDLER_ICP_ATTEMPTS0
88-
HANDLER_ICP_MATCH0
87+
HANDLER_ICP_ATTEMPTS1
88+
HANDLER_ICP_MATCH1
8989
select * from t10 force index(a) where a=10 and b+1 <3333 order by a asc, b asc;
9090
a b c
9191
10 10 10
@@ -105,15 +105,15 @@ a b c
105105
10 10 10
106106
explain select * from t10 force index(a) where a=10 and b+1 <3333 order by a asc, b desc;
107107
id select_type table type possible_keys key key_len ref rows Extra
108-
1 SIMPLE t10 ref a a 5 const 1 Using where
108+
1 SIMPLE t10 ref a a 5 const 1 Using index condition; Using where
109109
flush status;
110110
select * from t10 force index(a) where a=10 and b+1 <3333 order by a asc, b desc;
111111
a b c
112112
10 10 10
113113
SELECT * FROM information_schema.SESSION_STATUS WHERE VARIABLE_NAME LIKE '%icp%';
114114
VARIABLE_NAME VARIABLE_VALUE
115-
HANDLER_ICP_ATTEMPTS0
116-
HANDLER_ICP_MATCH0
115+
HANDLER_ICP_ATTEMPTS1
116+
HANDLER_ICP_MATCH1
117117
select * from t10 force index(a) where a=10 and b+1 <3333 order by a desc, b asc;
118118
a b c
119119
10 10 10
@@ -135,15 +135,15 @@ a b c
135135
3 30 300
136136
explain select * from t1 where a >= 3 and a <= 3 order by a desc, b desc;
137137
id select_type table type possible_keys key key_len ref rows Extra
138-
1 SIMPLE t1 range a a 5 NULL 1 Using where
138+
1 SIMPLE t1 range a a 5 NULL 1 Using index condition
139139
flush status;
140140
select * from t1 where a >= 3 and a <= 3 order by a desc, b desc;
141141
a b c
142142
3 30 300
143143
SELECT * FROM information_schema.SESSION_STATUS WHERE VARIABLE_NAME LIKE '%icp%';
144144
VARIABLE_NAME VARIABLE_VALUE
145-
HANDLER_ICP_ATTEMPTS0
146-
HANDLER_ICP_MATCH0
145+
HANDLER_ICP_ATTEMPTS1
146+
HANDLER_ICP_MATCH1
147147
select * from t1 where a >= 3 and a <= 3 order by a asc, b asc;
148148
a b c
149149
3 30 300
@@ -166,15 +166,15 @@ a b c
166166
2 20 200
167167
explain select * from t1 where a >= 2 and a <= 2 order by a desc, b desc;
168168
id select_type table type possible_keys key key_len ref rows Extra
169-
1 SIMPLE t1 range a a 5 NULL 1 Using where
169+
1 SIMPLE t1 range a a 5 NULL 1 Using index condition
170170
flush status;
171171
select * from t1 where a >= 2 and a <= 2 order by a desc, b desc;
172172
a b c
173173
2 20 200
174174
SELECT * FROM information_schema.SESSION_STATUS WHERE VARIABLE_NAME LIKE '%icp%';
175175
VARIABLE_NAME VARIABLE_VALUE
176-
HANDLER_ICP_ATTEMPTS0
177-
HANDLER_ICP_MATCH0
176+
HANDLER_ICP_ATTEMPTS1
177+
HANDLER_ICP_MATCH1
178178
select * from t1 where a >= 2 and a <= 2 order by a asc, b asc;
179179
a b c
180180
2 20 200
@@ -214,7 +214,7 @@ a b c
214214
3 3 3
215215
explain select * from t1 where a >= 3 and a <= 7 order by a desc;
216216
id select_type table type possible_keys key key_len ref rows Extra
217-
1 SIMPLE t1 range a a 4 NULL 5 Using where
217+
1 SIMPLE t1 range a a 4 NULL 5 Using index condition
218218
flush status;
219219
select * from t1 where a >= 3 and a <= 7 order by a desc;
220220
a b c
@@ -225,8 +225,8 @@ a b c
225225
3 3 3
226226
SELECT * FROM information_schema.SESSION_STATUS WHERE VARIABLE_NAME LIKE '%icp%';
227227
VARIABLE_NAME VARIABLE_VALUE
228-
HANDLER_ICP_ATTEMPTS0
229-
HANDLER_ICP_MATCH0
228+
HANDLER_ICP_ATTEMPTS6
229+
HANDLER_ICP_MATCH6
230230
select * from t1 where a >= 3 and a <= 7 order by a desc, b desc;
231231
a b c
232232
7 7 7
@@ -236,7 +236,7 @@ a b c
236236
3 3 3
237237
explain select * from t1 where a >= 3 and a <= 7 order by a desc, b desc;
238238
id select_type table type possible_keys key key_len ref rows Extra
239-
1 SIMPLE t1 range a a 4 NULL 5 Using where
239+
1 SIMPLE t1 range a a 4 NULL 5 Using index condition
240240
flush status;
241241
select * from t1 where a >= 3 and a <= 7 order by a desc, b desc;
242242
a b c
@@ -247,8 +247,8 @@ a b c
247247
3 3 3
248248
SELECT * FROM information_schema.SESSION_STATUS WHERE VARIABLE_NAME LIKE '%icp%';
249249
VARIABLE_NAME VARIABLE_VALUE
250-
HANDLER_ICP_ATTEMPTS0
251-
HANDLER_ICP_MATCH0
250+
HANDLER_ICP_ATTEMPTS6
251+
HANDLER_ICP_MATCH6
252252
drop table t1;
253253
create table t1 (
254254
pk int primary key,
@@ -273,6 +273,6 @@ select * from t1 where kp1 between 950 and 960 and kp2+1 >33333 order by kp1 des
273273
pk kp1 kp2 col1
274274
SELECT * FROM information_schema.SESSION_STATUS WHERE VARIABLE_NAME LIKE '%icp%';
275275
VARIABLE_NAME VARIABLE_VALUE
276-
HANDLER_ICP_ATTEMPTS0
276+
HANDLER_ICP_ATTEMPTS11
277277
HANDLER_ICP_MATCH 0
278278
drop table t1;

mysql-test/main/mdev-34413-icp-reverse-order.test

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
--source include/have_innodb.inc
21
--source include/have_partition.inc
32
--source include/have_sequence.inc
43

mysql-test/main/myisam_explain_non_select_all.result

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,7 +1779,7 @@ FLUSH STATUS;
17791779
FLUSH TABLES;
17801780
EXPLAIN EXTENDED SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
17811781
id select_type table type possible_keys key key_len ref rows filtered Extra
1782-
1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 8 100.00 Using where
1782+
1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 8 100.00 Using index condition
17831783
Warnings:
17841784
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` desc limit 5
17851785
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
@@ -2291,7 +2291,7 @@ FLUSH STATUS;
22912291
FLUSH TABLES;
22922292
EXPLAIN EXTENDED SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
22932293
id select_type table type possible_keys key key_len ref rows filtered Extra
2294-
1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 8 100.00 Using where
2294+
1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 8 100.00 Using index condition
22952295
Warnings:
22962296
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` desc limit 5
22972297
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution

mysql-test/main/myisam_icp.result

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ WHERE ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00'
165165
ORDER BY ts DESC
166166
LIMIT 2;
167167
id select_type table type possible_keys key key_len ref rows Extra
168-
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where
168+
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using index condition
169169

170170
DROP TABLE t1;
171171
#
@@ -1016,12 +1016,12 @@ set optimizer_switch='mrr=off';
10161016
# Must not use ICP:
10171017
explain select * from t1 where a between 5 and 8 order by a desc, col desc;
10181018
id select_type table type possible_keys key key_len ref rows Extra
1019-
1 SIMPLE t1 range a a 5 NULL 40 Using where
1019+
1 SIMPLE t1 range a a 5 NULL 40 Using index condition
10201020
set optimizer_switch= @tmp_10000051;
10211021
# Must not use ICP:
10221022
explain select * from t1 where a=3 and col > 500 order by a desc, col desc;
10231023
id select_type table type possible_keys key key_len ref rows Extra
1024-
1 SIMPLE t1 range a a 10 NULL 10 Using where
1024+
1 SIMPLE t1 range a a 10 NULL 10 Using index condition
10251025
drop table t0, t1;
10261026
#
10271027
# MDEV-13628: ORed condition in pushed index condition is not removed from the WHERE

mysql-test/main/order_by_optimizer_innodb.result

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ pk1 count(*)
4242
# The following should use range(ux_pk1_fd5), two key parts (key_len=5+8=13)
4343
EXPLAIN SELECT * FROM t2 USE INDEX(ux_pk1_fd5) WHERE pk1=9 AND fd5 < 500 ORDER BY fd5 DESC LIMIT 10;
4444
id select_type table type possible_keys key key_len ref rows Extra
45-
1 SIMPLE t2 range ux_pk1_fd5 ux_pk1_fd5 13 NULL 138 Using where
45+
1 SIMPLE t2 range ux_pk1_fd5 ux_pk1_fd5 13 NULL 138 Using index condition
4646
# This also must use range, not ref. key_len must be 13
4747
EXPLAIN SELECT * FROM t2 WHERE pk1=9 AND fd5 < 500 ORDER BY fd5 DESC LIMIT 10;
4848
id select_type table type possible_keys key key_len ref rows Extra
49-
1 SIMPLE t2 range PRIMARY,ux_pk1_fd5 ux_pk1_fd5 13 NULL 138 Using where
49+
1 SIMPLE t2 range PRIMARY,ux_pk1_fd5 ux_pk1_fd5 13 NULL 138 Using index condition
5050
drop table t2;
5151
#
5252
# MDEV-6814: Server crashes in calculate_key_len on query with ORDER BY

mysql-test/main/rowid_filter_innodb.result

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3826,15 +3826,18 @@ ANALYZE
38263826
"loops": 1,
38273827
"r_loops": 1,
38283828
"rows": 250,
3829-
"r_rows": 250,
3829+
"r_index_rows": 250,
3830+
"r_rows": 2,
38303831
"cost": "REPLACED",
38313832
"r_table_time_ms": "REPLACED",
38323833
"r_other_time_ms": "REPLACED",
38333834
"r_engine_stats": REPLACED,
38343835
"filtered": 4.799086094,
38353836
"r_total_filtered": 0.8,
3836-
"attached_condition": "t1.a <=> 30100 and t1.b in (30100,30101,30102) and 30100 + t1.pk > 38539",
3837-
"r_filtered": 0.8
3837+
"index_condition": "30100 + t1.pk > 38539",
3838+
"r_icp_filtered": 0.8,
3839+
"attached_condition": "t1.a <=> 30100 and t1.b in (30100,30101,30102)",
3840+
"r_filtered": 100
38383841
}
38393842
}
38403843
]
@@ -3870,15 +3873,18 @@ ANALYZE
38703873
"loops": 1,
38713874
"r_loops": 1,
38723875
"rows": 250,
3873-
"r_rows": 250,
3876+
"r_index_rows": 250,
3877+
"r_rows": 2,
38743878
"cost": "REPLACED",
38753879
"r_table_time_ms": "REPLACED",
38763880
"r_other_time_ms": "REPLACED",
38773881
"r_engine_stats": REPLACED,
38783882
"filtered": 4.799086094,
38793883
"r_total_filtered": 0.8,
3880-
"attached_condition": "t1.a <=> 30100 and t1.b in (30100,30101,30102) and 30100 + t1.pk > 38539",
3881-
"r_filtered": 0.8
3884+
"index_condition": "30100 + t1.pk > 38539",
3885+
"r_icp_filtered": 0.8,
3886+
"attached_condition": "t1.a <=> 30100 and t1.b in (30100,30101,30102)",
3887+
"r_filtered": 100
38823888
}
38833889
}
38843890
]

mysql-test/main/subselect.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3197,7 +3197,7 @@ ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899'
31973197
id select_type table type possible_keys key key_len ref rows Extra
31983198
1 PRIMARY t1 system PRIMARY NULL NULL NULL 1
31993199
1 PRIMARY r const PRIMARY PRIMARY 4 const 1
3200-
2 SUBQUERY t2 range cb cb 40 NULL 3 Using where
3200+
2 SUBQUERY t2 range cb cb 40 NULL 3 Using index condition
32013201
SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r
32023202
ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899'
32033203
ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10;

mysql-test/main/subselect_no_exists_to_in.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3200,7 +3200,7 @@ ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899'
32003200
id select_type table type possible_keys key key_len ref rows Extra
32013201
1 PRIMARY t1 system PRIMARY NULL NULL NULL 1
32023202
1 PRIMARY r const PRIMARY PRIMARY 4 const 1
3203-
2 SUBQUERY t2 range cb cb 40 NULL 3 Using where
3203+
2 SUBQUERY t2 range cb cb 40 NULL 3 Using index condition
32043204
SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r
32053205
ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899'
32063206
ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10;

mysql-test/main/subselect_no_mat.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3202,7 +3202,7 @@ ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899'
32023202
id select_type table type possible_keys key key_len ref rows Extra
32033203
1 PRIMARY t1 system PRIMARY NULL NULL NULL 1
32043204
1 PRIMARY r const PRIMARY PRIMARY 4 const 1
3205-
2 SUBQUERY t2 range cb cb 40 NULL 3 Using where
3205+
2 SUBQUERY t2 range cb cb 40 NULL 3 Using index condition
32063206
SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r
32073207
ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899'
32083208
ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10;

mysql-test/main/subselect_no_opts.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3198,7 +3198,7 @@ ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899'
31983198
id select_type table type possible_keys key key_len ref rows Extra
31993199
1 PRIMARY t1 system PRIMARY NULL NULL NULL 1
32003200
1 PRIMARY r const PRIMARY PRIMARY 4 const 1
3201-
2 SUBQUERY t2 range cb cb 40 NULL 3 Using where
3201+
2 SUBQUERY t2 range cb cb 40 NULL 3 Using index condition
32023202
SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r
32033203
ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899'
32043204
ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10;

0 commit comments

Comments
 (0)