Commit b729896d authored by Monty's avatar Monty

MDEV-28073 Query performance degradation in newer MariaDB versions when using many tables

The issue was that best_extension_by_limited_search() had to go through
too many plans with the same cost as there where many EQ_REF tables.

Fixed by shortcutting EQ_REF (AND REF) when the result only contains one
row. This got the optimization time down from hours to sub seconds.

The only known downside with this patch is that in some cases a table
with ref and 1 record may be used before on EQ_REF table. The faster
optimzation phase should compensate for this.
parent f7dd8799
This diff is collapsed.
...@@ -221,8 +221,7 @@ explain select * from t1 where a=1 or b=1 { ...@@ -221,8 +221,7 @@ explain select * from t1 where a=1 or b=1 {
} }
}, },
"rows_for_plan": 2, "rows_for_plan": 2,
"cost_for_plan": 2.884903732, "cost_for_plan": 2.884903732
"estimated_join_cardinality": 2
} }
] ]
}, },
......
...@@ -227,7 +227,7 @@ explain select * from t1 where pk1 != 0 and key1 = 1 { ...@@ -227,7 +227,7 @@ explain select * from t1 where pk1 != 0 and key1 = 1 {
}, },
"rows_for_plan": 1, "rows_for_plan": 1,
"cost_for_plan": 1.325146475, "cost_for_plan": 1.325146475,
"estimated_join_cardinality": 1 "pruned_by_hanging_leaf": true
} }
] ]
}, },
......
...@@ -107,8 +107,7 @@ select * from db1.t1 { ...@@ -107,8 +107,7 @@ select * from db1.t1 {
} }
}, },
"rows_for_plan": 3, "rows_for_plan": 3,
"cost_for_plan": 2.605126953, "cost_for_plan": 2.605126953
"estimated_join_cardinality": 3
} }
] ]
}, },
...@@ -229,8 +228,7 @@ select * from db1.v1 { ...@@ -229,8 +228,7 @@ select * from db1.v1 {
} }
}, },
"rows_for_plan": 3, "rows_for_plan": 3,
"cost_for_plan": 2.605126953, "cost_for_plan": 2.605126953
"estimated_join_cardinality": 3
} }
] ]
}, },
......
...@@ -466,11 +466,11 @@ where t0.a in ( select t1.a from t1,t2 where t2.a=t0.a and ...@@ -466,11 +466,11 @@ where t0.a in ( select t1.a from t1,t2 where t2.a=t0.a and
t1.b=t2.b); t1.b=t2.b);
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 5 100.00 Using where 1 PRIMARY t0 ALL NULL NULL NULL NULL 5 100.00 Using where
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t0.a 1 100.00 1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Start temporary
1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Using where; FirstMatch(t2) 1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t0.a 1 100.00 Using where; End temporary
Warnings: Warnings:
Note 1276 Field or reference 'test.t0.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t0.a' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t1`.`a` = `test`.`t0`.`a` and `test`.`t1`.`b` = `test`.`t2`.`b` Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t1`.`a` = `test`.`t0`.`a` and `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t2`.`b` = `test`.`t1`.`b`
update t1 set a=3, b=11 where a=4; update t1 set a=3, b=11 where a=4;
update t2 set b=11 where a=3; update t2 set b=11 where a=3;
select * from t0 where t0.a in select * from t0 where t0.a in
......
...@@ -477,11 +477,11 @@ where t0.a in ( select t1.a from t1,t2 where t2.a=t0.a and ...@@ -477,11 +477,11 @@ where t0.a in ( select t1.a from t1,t2 where t2.a=t0.a and
t1.b=t2.b); t1.b=t2.b);
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 5 100.00 Using where 1 PRIMARY t0 ALL NULL NULL NULL NULL 5 100.00 Using where
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t0.a 1 100.00 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan 1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Start temporary; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Using where; FirstMatch(t2); Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan 1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t0.a 1 100.00 Using where; End temporary; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan
Warnings: Warnings:
Note 1276 Field or reference 'test.t0.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t0.a' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t1`.`a` = `test`.`t0`.`a` and `test`.`t1`.`b` = `test`.`t2`.`b` Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t1`.`a` = `test`.`t0`.`a` and `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t2`.`b` = `test`.`t1`.`b`
update t1 set a=3, b=11 where a=4; update t1 set a=3, b=11 where a=4;
update t2 set b=11 where a=3; update t2 set b=11 where a=3;
# Not anymore: # Not anymore:
......
...@@ -468,11 +468,11 @@ where t0.a in ( select t1.a from t1,t2 where t2.a=t0.a and ...@@ -468,11 +468,11 @@ where t0.a in ( select t1.a from t1,t2 where t2.a=t0.a and
t1.b=t2.b); t1.b=t2.b);
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 5 100.00 Using where 1 PRIMARY t0 ALL NULL NULL NULL NULL 5 100.00 Using where
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t0.a 1 100.00 1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Start temporary
1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Using where; FirstMatch(t2) 1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t0.a 1 100.00 Using where; End temporary
Warnings: Warnings:
Note 1276 Field or reference 'test.t0.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t0.a' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t1`.`a` = `test`.`t0`.`a` and `test`.`t1`.`b` = `test`.`t2`.`b` Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t1`.`a` = `test`.`t0`.`a` and `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t2`.`b` = `test`.`t1`.`b`
update t1 set a=3, b=11 where a=4; update t1 set a=3, b=11 where a=4;
update t2 set b=11 where a=3; update t2 set b=11 where a=3;
select * from t0 where t0.a in select * from t0 where t0.a in
......
This diff is collapsed.
...@@ -989,6 +989,8 @@ class POSITION ...@@ -989,6 +989,8 @@ class POSITION
*/ */
enum sj_strategy_enum sj_strategy; enum sj_strategy_enum sj_strategy;
/* Type of join (EQ_REF, REF etc) */
enum join_type type;
/* /*
Valid only after fix_semijoin_strategies_for_picked_join_order() call: Valid only after fix_semijoin_strategies_for_picked_join_order() call:
if sj_strategy!=SJ_OPT_NONE, this is the number of subsequent tables that if sj_strategy!=SJ_OPT_NONE, this is the number of subsequent tables that
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment