Commit c467be8d authored by igor@rurik.mysql.com's avatar igor@rurik.mysql.com

Fixed bug #19579: at range analysis optimizer did not take into

account predicates that become sargable after reading const tables.
In some cases this resulted in choosing non-optimal execution plans.
Now info of such potentially saragable predicates is saved in
an array and after reading const tables we check whether this
predicates has become saragable.
parent abad78f4
......@@ -3552,3 +3552,52 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
1 SIMPLE t2 ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
DROP TABLE t1,t2;
CREATE TABLE t1(id int PRIMARY KEY, b int, e int);
CREATE TABLE t2(i int, a int, INDEX si(i), INDEX ai(a));
CREATE TABLE t3(a int PRIMARY KEY, c char(4), INDEX ci(c));
INSERT INTO t1 VALUES
(1,10,19), (2,20,22), (4,41,42), (9,93,95), (7, 77,79),
(6,63,67), (5,55,58), (3,38,39), (8,81,89);
INSERT INTO t2 VALUES
(21,210), (41,410), (82,820), (83,830), (84,840),
(65,650), (51,510), (37,370), (94,940), (76,760),
(22,220), (33,330), (40,400), (95,950), (38,380),
(67,670), (88,880), (57,570), (96,960), (97,970);
INSERT INTO t3 VALUES
(210,'bb'), (950,'ii'), (400,'ab'), (500,'ee'), (220,'gg'),
(440,'gg'), (310,'eg'), (380,'ee'), (840,'bb'), (830,'ff'),
(230,'aa'), (960,'ii'), (410,'aa'), (510,'ee'), (290,'bb'),
(450,'gg'), (320,'dd'), (390,'hh'), (850,'jj'), (860,'ff');
EXPLAIN
SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 range si si 5 NULL 4 Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2,t3
WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee') ;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 range si,ai si 5 NULL 4 Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 range si si 5 NULL 2 Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2,t3
WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 range si,ai si 5 NULL 2 Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
DROP TABLE t1,t2,t3;
......@@ -3007,6 +3007,8 @@ c7 int, c8 int, c9 int, fulltext key (`c1`));
select distinct match (`c1`) against ('z') , c2, c3, c4,c5, c6,c7, c8
from t1 where c9=1 order by c2, c2;
drop table t1;
#
# Bug #22735: no equality propagation for BETWEEN and IN with STRING arguments
#
......@@ -3033,3 +3035,46 @@ EXPLAIN SELECT t2.*
WHERE t2.fk IN ('a','b') AND t2.pk=t1.fk;
DROP TABLE t1,t2;
#
# Bug #19579: predicates that become sargable after reading const tables
# are not taken into account by optimizer
#
CREATE TABLE t1(id int PRIMARY KEY, b int, e int);
CREATE TABLE t2(i int, a int, INDEX si(i), INDEX ai(a));
CREATE TABLE t3(a int PRIMARY KEY, c char(4), INDEX ci(c));
INSERT INTO t1 VALUES
(1,10,19), (2,20,22), (4,41,42), (9,93,95), (7, 77,79),
(6,63,67), (5,55,58), (3,38,39), (8,81,89);
INSERT INTO t2 VALUES
(21,210), (41,410), (82,820), (83,830), (84,840),
(65,650), (51,510), (37,370), (94,940), (76,760),
(22,220), (33,330), (40,400), (95,950), (38,380),
(67,670), (88,880), (57,570), (96,960), (97,970);
INSERT INTO t3 VALUES
(210,'bb'), (950,'ii'), (400,'ab'), (500,'ee'), (220,'gg'),
(440,'gg'), (310,'eg'), (380,'ee'), (840,'bb'), (830,'ff'),
(230,'aa'), (960,'ii'), (410,'aa'), (510,'ee'), (290,'bb'),
(450,'gg'), (320,'dd'), (390,'hh'), (850,'jj'), (860,'ff');
EXPLAIN
SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee');
EXPLAIN
SELECT t3.a FROM t1,t2,t3
WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee') ;
EXPLAIN
SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
EXPLAIN
SELECT t3.a FROM t1,t2,t3
WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
DROP TABLE t1,t2,t3;
......@@ -1078,6 +1078,8 @@ bool Item_func_between::fix_fields(THD *thd, Item **ref)
if (Item_func_opt_neg::fix_fields(thd, ref))
return 1;
thd->lex->current_select->between_count++;
/* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */
if (pred_level && !negated)
return 0;
......
......@@ -4906,6 +4906,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
thd->set_query_id=1;
select_lex->cond_count= 0;
select_lex->between_count= 0;
for (table= tables; table; table= table->next_local)
{
......
......@@ -1138,7 +1138,7 @@ void st_select_lex::init_query()
initialization is checked for failure.
*/
parent_lex->push_context(&context);
cond_count= with_wild= 0;
cond_count= between_count= with_wild= 0;
conds_processed_with_permanent_arena= 0;
ref_pointer_array= 0;
select_n_having_items= 0;
......
......@@ -530,7 +530,8 @@ public:
list during split_sum_func
*/
uint select_n_having_items;
uint cond_count; /* number of arguments of and/or/xor in where/having */
uint cond_count; /* number of arguments of and/or/xor in where/having/on */
uint between_count; /* number of between predicates in where/having/on */
enum_parsing_place parsing_place; /* where we are parsing expression */
bool with_sum_func; /* sum function indicator */
/*
......
This diff is collapsed.
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