Skip to content

Commit 923094b

Browse files
MDEV-36094 Row ID filtering for reverse-ordered scans
The fix for MDEV-34413 added support for Index Condition Pushdown with reverse ordered scans. This makes Rowid filtering work with reverse-ordered scans, too, so enable it. For example, InnoDB can now check the pushed index condition and then check the rowid filter on success, in the ORDER BY ... DESC case.
1 parent 24b5c30 commit 923094b

File tree

4 files changed

+51
-56
lines changed

4 files changed

+51
-56
lines changed

mysql-test/main/mdev-36094-rowid-filter-reverse-scan.result

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ EXPLAIN
2929
"key": "t1_b",
3030
"key_length": "5",
3131
"used_key_parts": ["b"],
32+
"rowid_filter": {
33+
"range": {
34+
"key": "t1_a",
35+
"used_key_parts": ["a"]
36+
},
37+
"rows": 6,
38+
"selectivity_pct": 60
39+
},
3240
"loops": 1,
3341
"rows": 1,
3442
"cost": "COST_REPLACED",
@@ -66,6 +74,14 @@ EXPLAIN
6674
"key": "t1_b",
6775
"key_length": "5",
6876
"used_key_parts": ["b"],
77+
"rowid_filter": {
78+
"range": {
79+
"key": "t1_a",
80+
"used_key_parts": ["a"]
81+
},
82+
"rows": 8,
83+
"selectivity_pct": 80
84+
},
6985
"loops": 1,
7086
"rows": 2,
7187
"cost": "COST_REPLACED",
@@ -107,6 +123,14 @@ EXPLAIN
107123
"key": "t1_b",
108124
"key_length": "5",
109125
"used_key_parts": ["b"],
126+
"rowid_filter": {
127+
"range": {
128+
"key": "t1_a",
129+
"used_key_parts": ["a"]
130+
},
131+
"rows": 6,
132+
"selectivity_pct": 60
133+
},
110134
"loops": 1,
111135
"rows": 1,
112136
"cost": "COST_REPLACED",

mysql-test/main/rowid_filter_innodb.result

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3752,7 +3752,6 @@ analyze table t1;
37523752
Table Op Msg_type Msg_text
37533753
test.t1 analyze status Engine-independent statistics collected
37543754
test.t1 analyze status OK
3755-
# The following must NOT use Rowid Filter:
37563755
analyze format=json select * from t1
37573756
where
37583757
a =30100 and b in (30100,30101,30102)
@@ -3778,9 +3777,23 @@ ANALYZE
37783777
"key_length": "5",
37793778
"used_key_parts": ["a"],
37803779
"ref": ["const"],
3780+
"rowid_filter": {
3781+
"range": {
3782+
"key": "b",
3783+
"used_key_parts": ["b"]
3784+
},
3785+
"rows": 252,
3786+
"selectivity_pct": 4.799085888,
3787+
"r_rows": 250,
3788+
"r_lookups": 250,
3789+
"r_selectivity_pct": 100,
3790+
"r_buffer_size": "REPLACED",
3791+
"r_filling_time_ms": "REPLACED"
3792+
},
37813793
"loops": 1,
37823794
"r_loops": 1,
37833795
"rows": 250,
3796+
"r_index_rows": 250,
37843797
"r_rows": 250,
37853798
"cost": "REPLACED",
37863799
"r_table_time_ms": "REPLACED",
@@ -3870,6 +3883,19 @@ ANALYZE
38703883
"key_length": "5",
38713884
"used_key_parts": ["a"],
38723885
"ref": ["const"],
3886+
"rowid_filter": {
3887+
"range": {
3888+
"key": "b",
3889+
"used_key_parts": ["b"]
3890+
},
3891+
"rows": 252,
3892+
"selectivity_pct": 4.799085888,
3893+
"r_rows": 250,
3894+
"r_lookups": 2,
3895+
"r_selectivity_pct": 100,
3896+
"r_buffer_size": "REPLACED",
3897+
"r_filling_time_ms": "REPLACED"
3898+
},
38733899
"loops": 1,
38743900
"r_loops": 1,
38753901
"rows": 250,

mysql-test/main/rowid_filter_innodb.test

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,6 @@ from
810810
insert into t1 (a,b,f1) values ( 110, 100, 12345);
811811
analyze table t1;
812812

813-
--echo # The following must NOT use Rowid Filter:
814813
--source include/analyze-format.inc
815814
analyze format=json select * from t1
816815
where

sql/sql_select.cc

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -27056,47 +27056,6 @@ void compute_part_of_sort_key_for_equals(JOIN *join, TABLE *table,
2705627056
@detail
2705727057
- Disable "Range checked for each record" (Is this strictly necessary
2705827058
here?)
27059-
- Disable Rowid Filtering.
27060-
27061-
RowidFilteringAndReverseScans:
27062-
Suppose we're computing
27063-
27064-
select * from t1
27065-
where
27066-
key1 between 10 and 20 and extra_condition
27067-
order by key1 desc
27068-
27069-
here the range access uses a reverse-ordered scan on (1 <= key1 <= 10) and
27070-
extra_condition is checked by either ICP or Rowid Filtering.
27071-
27072-
Also suppose that extra_condition happens to be false for rows of t1 that
27073-
do not satisfy the "10 <= key1 <= 20" condition.
27074-
27075-
For forward ordered range scan, the SQL layer will make these calls:
27076-
27077-
h->read_range_first(RANGE(10 <= key1 <= 20));
27078-
while (h->read_range_next()) { ... }
27079-
27080-
The storage engine sees the end endpoint of "key1<=20" and can stop scanning
27081-
as soon as it encounters a row with key1>20.
27082-
27083-
For backward-ordered range scan, the SQL layer will make these calls:
27084-
27085-
h->index_read_map(key1=20, HA_READ_PREFIX_LAST_OR_PREV);
27086-
while (h->index_prev()) {
27087-
if (cmp_key(h->record, "key1=10" )<0)
27088-
break; // end of range
27089-
...
27090-
}
27091-
27092-
Note that the check whether we've walked beyond the key=10 endpoint is
27093-
made at the SQL layer. The storage engine has no information about the left
27094-
endpoint of the interval we're scanning. If all rows before that endpoint
27095-
do not pass the Rowid Filter, the storage engine will enumerate the records
27096-
until the table start.
27097-
27098-
In MySQL, the API is extended with set_end_range() call so that the storage
27099-
engine "knows" when to stop scanning.
2710027059
*/
2710127060

2710227061
static void prepare_for_reverse_ordered_access(JOIN_TAB *tab)
@@ -27107,19 +27066,6 @@ static void prepare_for_reverse_ordered_access(JOIN_TAB *tab)
2710727066
tab->use_quick= 1;
2710827067
tab->read_first_record= join_init_read_record;
2710927068
}
27110-
/*
27111-
Rowid filtering does not work with reverse scans so cancel it.
27112-
*/
27113-
{
27114-
/*
27115-
Rowid Filter is initialized at a later stage. It is not pushed to
27116-
the storage engine yet:
27117-
*/
27118-
DBUG_ASSERT(!tab->table->file->pushed_rowid_filter);
27119-
tab->range_rowid_filter_info= NULL;
27120-
delete tab->rowid_filter;
27121-
tab->rowid_filter= NULL;
27122-
}
2712327069
}
2712427070

2712527071

0 commit comments

Comments
 (0)