diff options
author | Evgeny Potemkin <epotemkin@mysql.com> | 2009-12-02 00:25:51 +0300 |
---|---|---|
committer | Evgeny Potemkin <epotemkin@mysql.com> | 2009-12-02 00:25:51 +0300 |
commit | 987e146604d741f13fa03b7cb5e4af1cf3e30324 (patch) | |
tree | f6897e6f5c940d328bb17f29511b4e7dc729185b /mysql-test | |
parent | 9e5d1bb6647c88e5a60c2a3e7eadc76fd1089135 (diff) | |
download | mariadb-git-987e146604d741f13fa03b7cb5e4af1cf3e30324.tar.gz |
Bug#33546: Slowdown on re-evaluation of constant expressions.
Constant expressions in WHERE/HAVING/ON clauses aren't cached and evaluated
for each row. This causes slowdown of query execution especially if constant
UDF/SP function are used.
Now WHERE/HAVING/ON expressions are analyzed in the top-bottom direction with
help of the compile function. When analyzer meets a constant item it
sets a flag for the tree transformer to cache the item and doesn't allow tree
walker to go deeper. Thus, the topmost item of a constant expression if
cached. This is done after all other optimizations were applied to
WHERE/HAVING/ON expressions
A helper function called cache_const_exprs is added to the JOIN class.
It calls compile method with caching analyzer and transformer on WHERE,
HAVING, ON expressions if they're present.
The cache_const_expr_analyzer and cache_const_expr_transformer functions are
added to the Item class. The first one check if the item can be cached and
the second caches it if so.
A new Item_cache_datetime class is derived from the Item_cache class.
It caches both int and string values of the underlying item independently to
avoid DATETIME aware int-to-string conversion. Thus it completely relies on
the ability of the underlying item to correctly convert DATETIME value from
int to string and vice versa.
mysql-test/r/func_like.result:
A test case result is corrected after fixing bug#33546.
mysql-test/r/func_time.result:
A test case result is corrected after fixing bug#33546.
mysql-test/r/select.result:
Added a test case for the bug#33546.
mysql-test/r/subselect.result:
A test case result is corrected after fixing bug#33546.
mysql-test/r/udf.result:
Added a test case for the bug#33546.
mysql-test/t/select.test:
Added a test case for the bug#33546.
mysql-test/t/udf.test:
Added a test case for the bug#33546.
sql/item.cc:
Bug#33546: Slowdown on re-evaluation of constant expressions.
The cache_const_expr_analyzer and cache_const_expr_transformer functions are
added to the Item class. The first one check if the item can be cached and
the second caches it if so.
Item_cache_datetime class implementation is added.
sql/item.h:
Bug#33546: Slowdown on re-evaluation of constant expressions.
Item_ref and Item_cache classes now returns basic_const_item
from underlying item.
The cache_const_expr_analyzer and cache_const_expr_transformer functions are
added to the Item class.
sql/sql_select.cc:
Bug#33546: Slowdown on re-evaluation of constant expressions.
A helper function called cache_const_exprs is added to the JOIN class.
It calls compile method with caching analyzer and transformer on WHERE,
HAVING, ON expressions if they're present.
sql/sql_select.h:
Bug#33546: Slowdown on re-evaluation of constant expressions.
A helper function called cache_const_exprs is added to the JOIN class.
Diffstat (limited to 'mysql-test')
-rw-r--r-- | mysql-test/r/func_like.result | 2 | ||||
-rw-r--r-- | mysql-test/r/func_time.result | 1 | ||||
-rw-r--r-- | mysql-test/r/select.result | 73 | ||||
-rw-r--r-- | mysql-test/r/subselect.result | 2 | ||||
-rw-r--r-- | mysql-test/r/udf.result | 15 | ||||
-rw-r--r-- | mysql-test/t/select.test | 41 | ||||
-rw-r--r-- | mysql-test/t/udf.test | 14 |
7 files changed, 143 insertions, 5 deletions
diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result index 9338a76e320..8d0f34f3bda 100644 --- a/mysql-test/r/func_like.result +++ b/mysql-test/r/func_like.result @@ -10,7 +10,7 @@ explain extended select * from t1 where a like concat('abc','%'); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 index a a 13 NULL 5 20.00 Using where; Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` like concat('abc','%')) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` like <cache>(concat('abc','%'))) select * from t1 where a like "abc%"; a abc diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 59527e0b418..7bcaf5567cf 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -928,7 +928,6 @@ select f1 from t1 where cast("2006-1-1" as date) between f1 and cast('zzz' as da f1 Warnings: Warning 1292 Incorrect datetime value: 'zzz' -Warning 1292 Incorrect datetime value: 'zzz' select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); f1 2006-01-01 diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 1944edf6ade..604ff2be532 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4423,9 +4423,14 @@ CREATE TABLE t1(a INT); INSERT INTO t1 VALUES (2),(3); # Should not crash SELECT 1 FROM t1 WHERE a <> 1 AND NOT -ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1)) +ROW(1,a) <=> ROW(1,(SELECT 1 FROM t1)) INTO @var0; ERROR 21000: Subquery returns more than 1 row +SELECT 1 FROM t1 WHERE a <> 1 AND NOT +ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1)); +1 +1 +1 DROP TABLE t1; End of 5.0 tests create table t1(a INT, KEY (a)); @@ -4577,4 +4582,70 @@ field2 15:13:38 drop table A,AA,B,BB; #end of test for bug#45266 +# +# Bug#33546: Slowdown on re-evaluation of constant expressions. +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (2); +SELECT * FROM t1 WHERE a = 1 + 1; +a +2 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = 1 + 1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = <cache>((1 + 1))) +SELECT * FROM t1 HAVING a = 1 + 1; +a +2 +EXPLAIN EXTENDED SELECT * FROM t1 HAVING a = 1 + 1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` having (`test`.`t1`.`a` = <cache>((1 + 1))) +SELECT * FROM t1, t2 WHERE a = b + (1 + 1); +a b +4 2 +EXPLAIN EXTENDED SELECT * FROM t1, t2 WHERE a = b + (1 + 1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 system NULL NULL NULL NULL 1 100.00 +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,'2' AS `b` from `test`.`t1` where (`test`.`t1`.`a` = <cache>(('2' + (1 + 1)))) +SELECT * FROM t2 LEFT JOIN t1 ON a = b + 1; +b a +2 3 +EXPLAIN EXTENDED SELECT * FROM t2 LEFT JOIN t1 ON a = b + 1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 system NULL NULL NULL NULL 1 100.00 +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 +Warnings: +Note 1003 select '2' AS `b`,`test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a > UNIX_TIMESTAMP('2009-03-10 00:00:00'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > <cache>(unix_timestamp('2009-03-10 00:00:00'))) +CREATE FUNCTION f1() RETURNS INT DETERMINISTIC +BEGIN +SET @cnt := @cnt + 1; +RETURN 1; +END;| +SET @cnt := 0; +SELECT * FROM t1 WHERE a = f1(); +a +1 +SELECT @cnt; +@cnt +1 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = f1(); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = <cache>(`f1`())) +DROP TABLE t1, t2; +DROP FUNCTION f1; +# End of bug#33546 End of 5.1 tests diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 6325dc4f2fc..c77912e69cb 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -735,7 +735,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1249 Select 3 was reduced during optimization Note 1249 Select 2 was reduced during optimization -Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where (`test`.`t2`.`id` = (1 + 1)) +Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where (`test`.`t2`.`id` = <cache>((1 + 1))) EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index NULL id 5 NULL 2 100.00 Using where; Using index diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index 601b364fbbe..fbf87b2e4cc 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -409,3 +409,18 @@ b 1 DROP TABLE t1; End of 5.0 tests. +# +# Bug#33546: Slowdown on re-evaluation of constant expressions. +# +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES(1),(50); +CREATE FUNCTION myfunc_double RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB"; +EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE f1=1 + myfunc_double(1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`f1` = <cache>((1 + myfunc_double(1 AS `1`)))) +DROP FUNCTION myfunc_double; +DROP TABLE t1; +# +End of 5.1 tests. diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 51f0cd73374..95c16849633 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3767,9 +3767,14 @@ INSERT INTO t1 VALUES (2),(3); --echo # Should not crash --error ER_SUBQUERY_NO_1_ROW SELECT 1 FROM t1 WHERE a <> 1 AND NOT -ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1)) +ROW(1,a) <=> ROW(1,(SELECT 1 FROM t1)) INTO @var0; +# Query correctly return 2 rows since comparison a <=> fisrt_subquery is +# always false, thus the second query is never executed. +SELECT 1 FROM t1 WHERE a <> 1 AND NOT +ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1)); + DROP TABLE t1; @@ -3918,4 +3923,38 @@ SELECT table1 .`time_key` field2 FROM B table1 LEFT JOIN BB JOIN A table5 ON drop table A,AA,B,BB; --echo #end of test for bug#45266 + +--echo # +--echo # Bug#33546: Slowdown on re-evaluation of constant expressions. +--echo # +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (2); +SELECT * FROM t1 WHERE a = 1 + 1; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = 1 + 1; +SELECT * FROM t1 HAVING a = 1 + 1; +EXPLAIN EXTENDED SELECT * FROM t1 HAVING a = 1 + 1; +SELECT * FROM t1, t2 WHERE a = b + (1 + 1); +EXPLAIN EXTENDED SELECT * FROM t1, t2 WHERE a = b + (1 + 1); +SELECT * FROM t2 LEFT JOIN t1 ON a = b + 1; +EXPLAIN EXTENDED SELECT * FROM t2 LEFT JOIN t1 ON a = b + 1; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a > UNIX_TIMESTAMP('2009-03-10 00:00:00'); + +delimiter |; +CREATE FUNCTION f1() RETURNS INT DETERMINISTIC +BEGIN + SET @cnt := @cnt + 1; + RETURN 1; +END;| +delimiter ;| + +SET @cnt := 0; +SELECT * FROM t1 WHERE a = f1(); +SELECT @cnt; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = f1(); +DROP TABLE t1, t2; +DROP FUNCTION f1; +--echo # End of bug#33546 + --echo End of 5.1 tests diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test index 7bf252040e5..7e383ce69fa 100644 --- a/mysql-test/t/udf.test +++ b/mysql-test/t/udf.test @@ -449,3 +449,17 @@ SELECT IF( a = 1, a, a ) AS `b` FROM t1 ORDER BY field( `b`, 1 ); DROP TABLE t1; --echo End of 5.0 tests. + +--echo # +--echo # Bug#33546: Slowdown on re-evaluation of constant expressions. +--echo # +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES(1),(50); +--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB +eval CREATE FUNCTION myfunc_double RETURNS INTEGER SONAME "$UDF_EXAMPLE_LIB"; +EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE f1=1 + myfunc_double(1); +DROP FUNCTION myfunc_double; +DROP TABLE t1; +--echo # +--echo End of 5.1 tests. + |