1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-35180: ref_to_range rewrite causes poor query plan

(Variant 2: only allow rewrite for ref(const))

make_join_select() has a "ref_to_range" rewrite: it would rewrite
any ref access to a range access on the same index if the latter uses
more keyparts.
It seems, he initial intent of this was to fix poor query plan choice
in cases like

  t.keypart1=const AND t.keypart2 < 'foo'

Due to deficiency in cost model, ref access could be picked while range
would enumerate fewer rows and be cheaper.
However, the condition also forces a rewrite in cases like:

  t.keypart1=prev_table.col AND t.keypart1<='foo' AND t.keypart2<'bar'

Here, it can be that
* keypart1=prev_table.col is highly selective
* (keypart1, keypart2) <= ('foo', 'bar') is not at all selective.

Still, the rewrite would be made and poor query plan chosen.
Fixed this by only doing the rewrite if ref access was ref(const)
so we can be certain that quick select also used these restrictions
and will scan a subset of rows that ref access would scan.
This commit is contained in:
Sergei Petrunia
2024-10-16 18:35:37 +03:00
parent 3a1cf2c85b
commit 0540eac05c
5 changed files with 99 additions and 10 deletions

View File

@ -1986,3 +1986,32 @@ explain select count(*) from t1, t2 as seq where a=11 and b=seq.seq;
drop table t1,t2;
set @@optimizer_adjust_secondary_key_costs=default;
--echo #
--echo # MDEV-35180: ref_to_range rewrite causes poor query plan
--echo #
create table t1 (a int);
insert into t1 select seq from seq_1_to_100;
create table t2 (
kp1 int,
kp2 int,
filler char(100),
key(kp1, kp2)
);
insert into t2
select
seq, seq,
'filler-data'
from seq_1_to_10000;
analyze table t1,t2;
--echo # For t2, this must use type=ref, key_len=5 (not type=range, key_len=10)
explain
select *
from t1, t2
where
t2.kp1=t1.a and t2.kp1<=100 and t2.kp2<=20;
drop table t1,t2;