MDEV-19820 Wrong result with multiple single column index request
The bug occured when the optimizer decided to use a rowid filter built by a range index scan to access an InnoDB table with generated clustered index. When a table is accessed by a secondary index Idx employing a rowid filter the the value of pk contained in the found index tuple is checked against the filter. A call of the handler function position is supposed to put the pk value into the handler::ref buffer. However for generated clustered primary keys it did not happened. The patch fixes this problem.
This commit is contained in:
parent
65368255ff
commit
1a518aa1d2
@ -2162,4 +2162,51 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select 1 AS `id`,`test`.`t2`.`y` AS `y`,`test`.`t2`.`x` AS `x` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`y` = 2 and `test`.`t2`.`x` = 1
|
Note 1003 select 1 AS `id`,`test`.`t2`.`y` AS `y`,`test`.`t2`.`x` AS `x` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`y` = 2 and `test`.`t2`.`x` = 1
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
|
#
|
||||||
|
# MDEV-19820: use of rowid filter for innodb table without primary key
|
||||||
|
#
|
||||||
|
create table t1 (a int, b int, key (b), key (a)) engine=innodb;
|
||||||
|
insert into t1
|
||||||
|
select (rand(1)*1000)/10, (rand(1001)*1000)/50 from seq_1_to_1000;
|
||||||
|
analyze table t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 analyze status Engine-independent statistics collected
|
||||||
|
test.t1 analyze status OK
|
||||||
|
set @save_optimizer_switch= @@optimizer_switch;
|
||||||
|
set optimizer_switch='rowid_filter=off';
|
||||||
|
select count(*) from t1 where a in (22,83,11) and b=2;
|
||||||
|
count(*)
|
||||||
|
6
|
||||||
|
explain extended select count(*) from t1 where a in (22,83,11) and b=2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 SIMPLE t1 ref b,a b 5 const 59 55.93 Using where
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`b` = 2 and `test`.`t1`.`a` in (22,83,11)
|
||||||
|
select * from t1 where a in (22,83,11) and b=2;
|
||||||
|
a b
|
||||||
|
11 2
|
||||||
|
11 2
|
||||||
|
83 2
|
||||||
|
11 2
|
||||||
|
83 2
|
||||||
|
22 2
|
||||||
|
set optimizer_switch='rowid_filter=on';
|
||||||
|
select count(*) from t1 where a in (22,83,11) and b=2;
|
||||||
|
count(*)
|
||||||
|
6
|
||||||
|
explain extended select count(*) from t1 where a in (22,83,11) and b=2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 SIMPLE t1 ref|filter b,a b|a 5|5 const 59 (3%) 55.93 Using where; Using rowid filter
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select count(0) AS `count(*)` from `test`.`t1` where `test`.`t1`.`b` = 2 and `test`.`t1`.`a` in (22,83,11)
|
||||||
|
select * from t1 where a in (22,83,11) and b=2;
|
||||||
|
a b
|
||||||
|
11 2
|
||||||
|
11 2
|
||||||
|
83 2
|
||||||
|
11 2
|
||||||
|
83 2
|
||||||
|
22 2
|
||||||
|
drop table t1;
|
||||||
|
set optimizer_switch=@save_optimizer_switch;
|
||||||
SET SESSION STORAGE_ENGINE=DEFAULT;
|
SET SESSION STORAGE_ENGINE=DEFAULT;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
SET SESSION STORAGE_ENGINE='InnoDB';
|
SET SESSION STORAGE_ENGINE='InnoDB';
|
||||||
|
|
||||||
--source rowid_filter.test
|
--source rowid_filter.test
|
||||||
|
--source include/have_sequence.inc
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # MDEV-18755: possible RORI-plan and possible plan with range filter
|
--echo # MDEV-18755: possible RORI-plan and possible plan with range filter
|
||||||
@ -65,4 +66,33 @@ eval explain extended $q;
|
|||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-19820: use of rowid filter for innodb table without primary key
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
create table t1 (a int, b int, key (b), key (a)) engine=innodb;
|
||||||
|
insert into t1
|
||||||
|
select (rand(1)*1000)/10, (rand(1001)*1000)/50 from seq_1_to_1000;
|
||||||
|
analyze table t1;
|
||||||
|
|
||||||
|
let $q=
|
||||||
|
select count(*) from t1 where a in (22,83,11) and b=2;
|
||||||
|
let $q1=
|
||||||
|
select * from t1 where a in (22,83,11) and b=2;
|
||||||
|
|
||||||
|
set @save_optimizer_switch= @@optimizer_switch;
|
||||||
|
|
||||||
|
set optimizer_switch='rowid_filter=off';
|
||||||
|
eval $q;
|
||||||
|
eval explain extended $q;
|
||||||
|
eval $q1;
|
||||||
|
|
||||||
|
set optimizer_switch='rowid_filter=on';
|
||||||
|
eval $q;
|
||||||
|
eval explain extended $q;
|
||||||
|
eval $q1;
|
||||||
|
|
||||||
|
drop table t1;
|
||||||
|
set optimizer_switch=@save_optimizer_switch;
|
||||||
|
|
||||||
SET SESSION STORAGE_ENGINE=DEFAULT;
|
SET SESSION STORAGE_ENGINE=DEFAULT;
|
||||||
|
@ -3902,11 +3902,25 @@ row_search_idx_cond_check(
|
|||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case ICP_MATCH:
|
case ICP_MATCH:
|
||||||
if (handler_rowid_filter_is_active(prebuilt->pk_filter)
|
if (handler_rowid_filter_is_active(prebuilt->pk_filter)) {
|
||||||
&& !handler_rowid_filter_check(prebuilt->pk_filter)) {
|
ut_ad(!prebuilt->index->is_primary());
|
||||||
|
if (prebuilt->clust_index_was_generated) {
|
||||||
|
ulint len;
|
||||||
|
dict_index_t* index = prebuilt->index;
|
||||||
|
const byte* data = rec_get_nth_field(
|
||||||
|
rec, offsets, index->n_fields - 1,
|
||||||
|
&len);
|
||||||
|
ut_ad(dict_index_get_nth_col(index,
|
||||||
|
index->n_fields - 1)
|
||||||
|
->prtype == (DATA_ROW_ID | DATA_NOT_NULL));
|
||||||
|
ut_ad(len == DATA_ROW_ID_LEN);
|
||||||
|
memcpy(prebuilt->row_id, data, DATA_ROW_ID_LEN);
|
||||||
|
}
|
||||||
|
if (!handler_rowid_filter_check(prebuilt->pk_filter)) {
|
||||||
MONITOR_INC(MONITOR_ICP_MATCH);
|
MONITOR_INC(MONITOR_ICP_MATCH);
|
||||||
return(ICP_NO_MATCH);
|
return(ICP_NO_MATCH);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* Convert the remaining fields to MySQL format.
|
/* Convert the remaining fields to MySQL format.
|
||||||
If this is a secondary index record, we must defer
|
If this is a secondary index record, we must defer
|
||||||
this until we have fetched the clustered index record. */
|
this until we have fetched the clustered index record. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user