MDEV-21243: Join buffer: condition is checked in wrong place for range access
In this scenario: - There is a possible range access for table T - And there is a ref access on the same index which uses fewer key parts - The join optimizer picks the ref access (because it is cheaper) - make_join_select applies this heuristic to switch to range: /* Range uses longer key; Use this instead of ref on key */ Join buffer will be used without having called JOIN_TAB::make_scan_filter(). This means, conditions that should be checked when reading table T will be checked after T is joined with the contents of the join buffer, instead. Fixed this by adding a make_scan_filter() check. (updated patch after backport to 10.3) (Fix testcase on Windows)
This commit is contained in:
parent
cba9ed1279
commit
9c3eca8514
@ -6056,4 +6056,76 @@ select f2 from t2,t1 where f2 = 0;
|
||||
f2
|
||||
drop table t1, t2;
|
||||
set join_buffer_size=@save_join_buffer_size;
|
||||
#
|
||||
# MDEV-21243: Join buffer: condition is checked in wrong place for range access
|
||||
#
|
||||
create table t1(a int primary key);
|
||||
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
create table t2 (a int);
|
||||
insert into t2 select A.a + 10*B.a from t1 A, t1 B;
|
||||
create table t3 (
|
||||
kp1 int,
|
||||
kp2 int,
|
||||
col1 int,
|
||||
col2 int,
|
||||
key (kp1, kp2)
|
||||
);
|
||||
insert into t3
|
||||
select
|
||||
A.a,
|
||||
B.a,
|
||||
A.a + 100*B.a,
|
||||
A.a + 100*B.a
|
||||
from
|
||||
t2 A, t2 B;
|
||||
analyze table t3;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t3 analyze status Table is already up to date
|
||||
# The following must have "B.col1 + 1 < 33333" attached to table B
|
||||
# and not to the block-nl-join node:
|
||||
explain format=json
|
||||
select *
|
||||
from t1 a, t3 b
|
||||
where
|
||||
b.kp1=a.a and
|
||||
b.kp1 <= 10 and
|
||||
b.kp2 <= 10 and
|
||||
b.col1 +1 < 33333;
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"table": {
|
||||
"table_name": "a",
|
||||
"access_type": "index",
|
||||
"possible_keys": ["PRIMARY"],
|
||||
"key": "PRIMARY",
|
||||
"key_length": "4",
|
||||
"used_key_parts": ["a"],
|
||||
"rows": 10,
|
||||
"filtered": 100,
|
||||
"attached_condition": "a.a <= 10",
|
||||
"using_index": true
|
||||
},
|
||||
"block-nl-join": {
|
||||
"table": {
|
||||
"table_name": "b",
|
||||
"access_type": "range",
|
||||
"possible_keys": ["kp1"],
|
||||
"key": "kp1",
|
||||
"key_length": "10",
|
||||
"used_key_parts": ["kp1", "kp2"],
|
||||
"rows": 836,
|
||||
"filtered": 11.962,
|
||||
"index_condition": "b.kp2 <= 10",
|
||||
"attached_condition": "b.kp2 <= 10 and b.col1 + 1 < 33333"
|
||||
},
|
||||
"buffer_type": "flat",
|
||||
"buffer_size": "256Kb",
|
||||
"join_type": "BNL",
|
||||
"attached_condition": "b.kp1 = a.a"
|
||||
}
|
||||
}
|
||||
}
|
||||
drop table t1,t2,t3;
|
||||
set @@optimizer_switch=@save_optimizer_switch;
|
||||
|
@ -4014,5 +4014,45 @@ select f2 from t2,t1 where f2 = 0;
|
||||
drop table t1, t2;
|
||||
set join_buffer_size=@save_join_buffer_size;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-21243: Join buffer: condition is checked in wrong place for range access
|
||||
--echo #
|
||||
create table t1(a int primary key);
|
||||
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
create table t2 (a int);
|
||||
insert into t2 select A.a + 10*B.a from t1 A, t1 B;
|
||||
|
||||
create table t3 (
|
||||
kp1 int,
|
||||
kp2 int,
|
||||
col1 int,
|
||||
col2 int,
|
||||
key (kp1, kp2)
|
||||
);
|
||||
|
||||
insert into t3
|
||||
select
|
||||
A.a,
|
||||
B.a,
|
||||
A.a + 100*B.a,
|
||||
A.a + 100*B.a
|
||||
from
|
||||
t2 A, t2 B;
|
||||
analyze table t3;
|
||||
|
||||
--echo # The following must have "B.col1 + 1 < 33333" attached to table B
|
||||
--echo # and not to the block-nl-join node:
|
||||
explain format=json
|
||||
select *
|
||||
from t1 a, t3 b
|
||||
where
|
||||
b.kp1=a.a and
|
||||
b.kp1 <= 10 and
|
||||
b.kp2 <= 10 and
|
||||
b.col1 +1 < 33333;
|
||||
|
||||
drop table t1,t2,t3;
|
||||
|
||||
# The following command must be the last one in the file
|
||||
set @@optimizer_switch=@save_optimizer_switch;
|
||||
|
@ -10966,6 +10966,13 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
||||
if (i != join->const_tables && tab->use_quick != 2 &&
|
||||
!tab->first_inner)
|
||||
{ /* Read with cache */
|
||||
/*
|
||||
TODO: the execution also gets here when we will not be using
|
||||
join buffer. Review these cases and perhaps, remove this call.
|
||||
(The final decision whether to use join buffer is made in
|
||||
check_join_cache_usage, so we should only call make_scan_filter()
|
||||
there, too).
|
||||
*/
|
||||
if (tab->make_scan_filter())
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
@ -11928,6 +11935,9 @@ uint check_join_cache_usage(JOIN_TAB *tab,
|
||||
if ((tab->cache= new (root) JOIN_CACHE_BNL(join, tab, prev_cache)))
|
||||
{
|
||||
tab->icp_other_tables_ok= FALSE;
|
||||
/* If make_join_select() hasn't called make_scan_filter(), do it now */
|
||||
if (!tab->cache_select && tab->make_scan_filter())
|
||||
goto no_join_cache;
|
||||
return (2 - MY_TEST(!prev_cache));
|
||||
}
|
||||
goto no_join_cache;
|
||||
|
Loading…
x
Reference in New Issue
Block a user