1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-21383: Possible range plan is not used under certain conditions

[Variant 2 of the fix: collect the attached conditions]

Problem:
make_join_select() has a section of code which starts with
 "We plan to scan all rows. Check again if we should use an index."

the code in that section will [unnecessarily] re-run the range
optimizer using this condition:

  condition_attached_to_current_table AND current_table's_ON_expr

Note that the original invocation of range optimizer in
make_join_statistics was done using the whole select's WHERE condition.
Taking the whole select's WHERE condition and using multiple-equalities
allowed the range optimizer to infer more range restrictions.

The fix:
- Do range optimization using a condition that is an AND of this table's
condition and all of the previous tables' conditions.
- Also, fix the range optimizer to prefer SEL_ARGs with type=KEY_RANGE
over SEL_ARGS with type=MAYBE_KEY, regardless of the key part.
Computing
key_and(
  SEL_ARG(type=MAYBE_KEY key_part=1),
  SEL_ARG(type=KEY_RANGE, key_part=2)
)
will now produce the SEL_ARG with type=KEY_RANGE.
This commit is contained in:
Sergei Petrunia
2020-01-20 00:06:51 +03:00
parent ade89fc898
commit 7e8a58020b
4 changed files with 194 additions and 1 deletions

View File

@ -1748,3 +1748,68 @@ show keys from t1;
explain select * from t0,t1 where t0.a=t1.a;
drop table t0,t1;
--echo #
--echo # MDEV-21383: Possible range plan is not used under certain conditions
--echo #
--disable_warnings
drop table if exists t10, t1000, t03;
--enable_warnings
create table t10(a int);
insert into t10 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1000(a int);
insert into t1000 select A.a + B.a* 10 + C.a * 100 from t10 A, t10 B, t10 C;
create table t03(a int);
insert into t03 values (0),(1),(2);
create table t1 (
stationid int
);
insert into t1 select a from t10;
CREATE TABLE t2 (
stationId int,
startTime int,
filler char(100),
key1 int,
key2 int,
key(key1),
key(key2),
PRIMARY KEY (`stationId`,`startTime`)
);
insert into t2 select
A.a,
B.a,
repeat('filler=data-', 4),
B.a,
1
from
t03 A,
t1000 B;
analyze table t2;
create table t3(a int, filler char(100), key(a));
insert into t3 select A.a+1000*B.a, 'filler-data' from t1000 A, t10 B;
--echo # This should produce a join order of t1,t2,t3
--echo # t2 should have type=range, key=PRIMARY key_len=8 (not type=ALL or key_len<8)
explain
SELECT *
FROM
t1,t2,t3
WHERE
t2.startTime <= 100 and
t2.stationId = t1.stationId and
(t1.stationid = 1 or t1.stationid = 2 or t1.stationid = 3) and
key1 >0 and
t2.key2=t3.a;
drop table t1,t2,t3;
drop table t1000,t10,t03;