Commit e85a4cb6 authored by unknown's avatar unknown

MWL#89: Cost-based choice between Materialization and IN->EXISTS transformation

- Added more tests to the MWL#89 specific test, and made the test more modular.
- Updated test files.
- Fixed a memory leak.
- More comments.

mysql-test/r/subselect_mat.result:
  - Updated the test file to reflect the new optimizer switches related to
    materialized subquery execution.
  - Added one extra test to test all cases that expose BUG#40037 (this is an old bug from 5.x).
  - Updated the test result with correct results that expose BUG#40037.
mysql-test/t/subselect_mat.test:
  - Updated the test file to reflect the new optimizer switches related to
    materialized subquery execution.
  - Added one extra test to test all cases that expose BUG#40037 (this is an old bug from 5.x).
  - Updated the test result with correct results that expose BUG#40037.
sql/sql_select.cc:
  Fixed a memory leak reported by Valgrind.
parent addd5782
-- echo
-- echo /* A. Subqueries in the SELECT clause. */
explain
select a1, a1 in (select b1 from t2 where b1 > '0') from t1;
select a1, a1 in (select b1 from t2 where b1 > '0') from t1;
-- echo
explain
select a1, a2, (a1, a2) in (select b1, b2 from t2 where b1 > '0') from t1;
select a1, a2, (a1, a2) in (select b1, b2 from t2 where b1 > '0') from t1;
-- echo
explain
select a1, a2, (a1, a2) in (select b1, b2 from t2 where b1 > '0' and b1 < '9') from t1;
select a1, a2, (a1, a2) in (select b1, b2 from t2 where b1 > '0' and b1 < '9') from t1;
-- echo
-- echo /*
-- echo B. "Natural" examples of subqueries without grouping that
-- echo cannot be flattened into semijoin.
-- echo */
explain
select a1 from t1 where a1 in (select b2 from t2) or a2 < '9';
select a1 from t1 where a1 in (select b2 from t2) or a2 < '9';
-- echo
explain
select a1, a2 from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0') or a2 < '9';
select a1, a2 from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0') or a2 < '9';
-- echo UNION subqueries are currently limited to only use IN-TO-EXISTS.
explain
select a2 from t1 where a2 in (select b2 from t2 UNION select b3 from t2 as t3);
select a2 from t1 where a2 in (select b2 from t2 UNION select b3 from t2 as t3);
-- echo
explain
select a1 from t1 where a1 = '1 - 02' and a1 in (select max(b1) from t2 where b2 = '2 - 02');
select a1 from t1 where a1 = '1 - 02' and a1 in (select max(b1) from t2 where b2 = '2 - 02');
-- echo
explain
select a1, a2 from t1 where (a1, a2) in (select b1, b2 from t2 order by b3);
select a1, a2 from t1 where (a1, a2) in (select b1, b2 from t2 order by b3);
-- echo
-- echo /* C. Subqueries in the WHERE clause with GROUP BY. */
explain
select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1);
select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1);
-- echo
explain
select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2);
select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2);
-- echo
explain
select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2 having b2 < '2 - 04');
select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2 having b2 < '2 - 04');
-- echo
explain
select * from t1 where (a1, a2, a3) in (select b1, b2, b3 from t2 group by b1, b2, b3);
select * from t1 where (a1, a2, a3) in (select b1, b2, b3 from t2 group by b1, b2, b3);
-- echo
explain
select * from t1 where (a1, a2, a3) in (select b1, b2, b3 from t2 where b3 = '3 - 02' group by b1, b2);
select * from t1 where (a1, a2, a3) in (select b1, b2, b3 from t2 where b3 = '3 - 02' group by b1, b2);
-- echo
explain
select * from t1 where (a1,a2,a3) in (select b1,b2,b3 from t2 where b1 = '1 - 01' group by b1,b2,b3);
select * from t1 where (a1,a2,a3) in (select b1,b2,b3 from t2 where b1 = '1 - 01' group by b1,b2,b3);
-- echo
-- echo /*
-- echo D. Subqueries for which materialization is not possible, and the
-- echo optimizer reverts to in-to-exists.
-- echo */
# The first two cases are rejected during the prepare phase by the procedure
# subquery_types_allow_materialization().
explain
select left(a1,7), left(a2,7) from t1_1024 where a1 in (select b1 from t2_1024 where b1 > '0') or a2 < '9';
select left(a1,7), left(a2,7) from t1_1024 where a1 in (select b1 from t2_1024 where b1 > '0') or a2 < '9';
explain
select left(a1,7), left(a2,7) from t1_1024 where (a1,a2) in (select b1, b2 from t2_1024 where b1 > '0') or a2 < '9';
select left(a1,7), left(a2,7) from t1_1024 where (a1,a2) in (select b1, b2 from t2_1024 where b1 > '0') or a2 < '9';
-- echo
# The following two subqueries return the result of a string function with a
# blob argument, where the return type may be != blob. These are rejected during
# cost-based optimization when attempting to create a temporary table.
explain
select left(a1,7), left(a2,7) from t1_1024 where a1 in (select substring(b1,1,1024) from t2_1024 where b1 > '0') or a2 < '9';
select left(a1,7), left(a2,7) from t1_1024 where a1 in (select substring(b1,1,1024) from t2_1024 where b1 > '0') or a2 < '9';
explain
select left(a1,7), left(a2,7) from t1_1024 where (a1,a2) in (select substring(b1,1,1024), substring(b2,1,1024) from t2_1024 where b1 > '0') or a2 < '9';
select left(a1,7), left(a2,7) from t1_1024 where (a1,a2) in (select substring(b1,1,1024), substring(b2,1,1024) from t2_1024 where b1 > '0') or a2 < '9';
-- echo
-- echo
-- echo /* E. Edge cases. */
-- echo
-- echo /* E.1 Both materialization and in_to_exists cannot be off. */
set @save_optimizer_switch=@@optimizer_switch;
set @@optimizer_switch = 'materialization=off,in_to_exists=off';
--error ER_ILLEGAL_SUBQUERY_OPTIMIZER_SWITCHES
select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1);
set @@optimizer_switch = @save_optimizer_switch;
-- echo /* E.2 Outer query without tables, always uses IN-TO-EXISTS. */
explain
select '1 - 03' in (select b1 from t2 where b1 > '0');
select '1 - 03' in (select b1 from t2 where b1 > '0');
-- echo /* E.3 Subqueries without tables. */
explain
select a1 from t1 where a1 in (select '1 - 03') or a2 < '9';
select a1 from t1 where a1 in (select '1 - 03') or a2 < '9';
-- echo UNION subqueries are currently limited to only use IN-TO-EXISTS.
explain
select a1 from t1 where a1 in (select '1 - 03' UNION select '1 - 02');
select a1 from t1 where a1 in (select '1 - 03' UNION select '1 - 02');
-- echo /* E.4 optimize_cond detects FALSE where/having clause. */
explain
select a1 from t1 where a1 in (select b1 from t2 where b1 = b2 and b2 = '1 - 03' and b1 = '1 - 02' ) or a2 < '9';
select a1 from t1 where a1 in (select b1 from t2 where b1 = b2 and b2 = '1 - 03' and b1 = '1 - 02' ) or a2 < '9';
-- echo /* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
-- echo TODO this test produces wrong result due to missing logic to handle the case
-- echo when JOIN::optimize detects an empty subquery result.
#explain
#select a1 from t1 where a1 in (select max(b1) from t2);
#select a1 from t1 where a1 in (select max(b1) from t2);
-- echo
#explain
#select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
#select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
-- echo /* E.6 make_join_select detects impossible WHERE. *
-- echo TODO
-- echo /* E.7 constant optimization detects "no matching row in const table". */
-- echo TODO
-- echo /* E.8 Impossible WHERE noticed after reading const tables. */
explain
select '1 - 03' in (select b1 from t2 where b1 > '0' and b1 < '0');
select '1 - 03' in (select b1 from t2 where b1 > '0' and b1 < '0');
-- echo
-- echo /* F. UPDATE/DELETE with subqueries. */
-- echo
-- echo TODO
-- echo
...@@ -30,7 +30,7 @@ create index it3i3 on t3i (c1, c2); ...@@ -30,7 +30,7 @@ create index it3i3 on t3i (c1, c2);
insert into t1i select * from t1; insert into t1i select * from t1;
insert into t2i select * from t2; insert into t2i select * from t2;
insert into t3i select * from t3; insert into t3i select * from t3;
set @@optimizer_switch='semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
/****************************************************************************** /******************************************************************************
* Simple tests. * Simple tests.
******************************************************************************/ ******************************************************************************/
...@@ -176,33 +176,33 @@ a1 a2 ...@@ -176,33 +176,33 @@ a1 a2
1 - 02 2 - 02 1 - 02 2 - 02
select * from t1 where (a1, a2) in (select b1, min(b2) from t2i limit 1,1); select * from t1 where (a1, a2) in (select b1, min(b2) from t2i limit 1,1);
ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=on';
prepare st1 from prepare st1 from
"select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1)"; "select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1)";
set @@optimizer_switch='default,materialization=off'; set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=on';
execute st1; execute st1;
a1 a2 a1 a2
1 - 01 2 - 01 1 - 01 2 - 01
1 - 02 2 - 02 1 - 02 2 - 02
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=on';
execute st1; execute st1;
a1 a2 a1 a2
1 - 01 2 - 01 1 - 01 2 - 01
1 - 02 2 - 02 1 - 02 2 - 02
set @@optimizer_switch='default,materialization=off'; set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=on';
prepare st1 from prepare st1 from
"select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1)"; "select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1)";
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
execute st1; execute st1;
a1 a2 a1 a2
1 - 01 2 - 01 1 - 01 2 - 01
1 - 02 2 - 02 1 - 02 2 - 02
set @@optimizer_switch='default,materialization=off'; set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=on';
execute st1; execute st1;
a1 a2 a1 a2
1 - 01 2 - 01 1 - 01 2 - 01
1 - 02 2 - 02 1 - 02 2 - 02
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
explain extended explain extended
select * from t1 where (a1, a2) in (select b1, b2 from t2 order by b1, b2); select * from t1 where (a1, a2) in (select b1, b2 from t2 order by b1, b2);
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
...@@ -549,7 +549,7 @@ a1 a2 ...@@ -549,7 +549,7 @@ a1 a2
Test that BLOBs are not materialized (except when arguments of some functions). Test that BLOBs are not materialized (except when arguments of some functions).
*/ */
# force materialization to be always considered # force materialization to be always considered
set @@optimizer_switch='semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
set @prefix_len = 6; set @prefix_len = 6;
set @blob_len = 16; set @blob_len = 16;
set @suffix_len = @blob_len - @prefix_len; set @suffix_len = @blob_len - @prefix_len;
...@@ -951,7 +951,7 @@ insert into t1bit values (b'010', b'110'); ...@@ -951,7 +951,7 @@ insert into t1bit values (b'010', b'110');
insert into t2bit values (b'001', b'101'); insert into t2bit values (b'001', b'101');
insert into t2bit values (b'010', b'110'); insert into t2bit values (b'010', b'110');
insert into t2bit values (b'110', b'111'); insert into t2bit values (b'110', b'111');
set @@optimizer_switch='semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
explain extended select bin(a1), bin(a2) explain extended select bin(a1), bin(a2)
from t1bit from t1bit
where (a1, a2) in (select b1, b2 from t2bit); where (a1, a2) in (select b1, b2 from t2bit);
...@@ -994,7 +994,7 @@ drop table t1, t2, t3, t1i, t2i, t3i, columns; ...@@ -994,7 +994,7 @@ drop table t1, t2, t3, t1i, t2i, t3i, columns;
/****************************************************************************** /******************************************************************************
* Test the cache of the left operand of IN. * Test the cache of the left operand of IN.
******************************************************************************/ ******************************************************************************/
set @@optimizer_switch='semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
create table t1 (s1 int); create table t1 (s1 int);
create table t2 (s2 int); create table t2 (s2 int);
insert into t1 values (5),(1),(0); insert into t1 values (5),(1),(0);
...@@ -1136,27 +1136,40 @@ drop table t2; ...@@ -1136,27 +1136,40 @@ drop table t2;
create table t1 (a1 int key); create table t1 (a1 int key);
create table t2 (b1 int); create table t2 (b1 int);
insert into t1 values (5); insert into t1 values (5);
Only the last query returns correct result. Filed as BUG#40037.
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1); explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found 2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
select min(a1) from t1 where 7 in (select b1 from t2 group by b1); select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
min(a1) min(a1)
set @@optimizer_switch='default,materialization=off'; NULL
set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=off';
explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1); explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found 2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
select min(a1) from t1 where 7 in (select b1 from t2 group by b1); select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
min(a1) min(a1)
set @@optimizer_switch='default,semijoin=off'; NULL
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
explain select min(a1) from t1 where 7 in (select b1 from t2); explain select min(a1) from t1 where 7 in (select b1 from t2);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found 2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
select min(a1) from t1 where 7 in (select b1 from t2); select min(a1) from t1 where 7 in (select b1 from t2);
min(a1) min(a1)
set @@optimizer_switch='default,materialization=off'; NULL
set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=off';
explain select min(a1) from t1 where 7 in (select b1 from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
select min(a1) from t1 where 7 in (select b1 from t2);
min(a1)
NULL
set @@optimizer_switch='materialization=off,in_to_exists=off,semijoin=on';
explain select min(a1) from t1 where 7 in (select b1 from t2); explain select min(a1) from t1 where 7 in (select b1 from t2);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
...@@ -1167,7 +1180,7 @@ drop table t1,t2; ...@@ -1167,7 +1180,7 @@ drop table t1,t2;
create table t1 (a char(2), b varchar(10)); create table t1 (a char(2), b varchar(10));
insert into t1 values ('a', 'aaa'); insert into t1 values ('a', 'aaa');
insert into t1 values ('aa', 'aaaa'); insert into t1 values ('aa', 'aaaa');
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
explain select a,b from t1 where b in (select a from t1); explain select a,b from t1 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
...@@ -1187,7 +1200,7 @@ INSERT INTO t1 (f1, f2) VALUES (10, 1.668); ...@@ -1187,7 +1200,7 @@ INSERT INTO t1 (f1, f2) VALUES (10, 1.668);
CREATE TABLE t2 LIKE t1; CREATE TABLE t2 LIKE t1;
INSERT INTO t2 VALUES (1, 1.789); INSERT INTO t2 VALUES (1, 1.789);
INSERT INTO t2 VALUES (13, 1.454); INSERT INTO t2 VALUES (13, 1.454);
SET @@optimizer_switch='default,semijoin=on,materialization=on'; SET @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=on';
EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2); EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 2 1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 2
...@@ -1208,7 +1221,7 @@ PRIMARY KEY (pk) ...@@ -1208,7 +1221,7 @@ PRIMARY KEY (pk)
INSERT INTO t1 VALUES (1,'o','ffff','ffff','ffoo'),(2,'f','ffff','ffff','ffff'); INSERT INTO t1 VALUES (1,'o','ffff','ffff','ffoo'),(2,'f','ffff','ffff','ffff');
CREATE TABLE t2 LIKE t1; CREATE TABLE t2 LIKE t1;
INSERT INTO t2 VALUES (1,'i','iiii','iiii','iiii'),(2,'f','ffff','ffff','ffff'); INSERT INTO t2 VALUES (1,'i','iiii','iiii','iiii'),(2,'f','ffff','ffff','ffff');
SET @@optimizer_switch='default,semijoin=on,materialization=on'; SET @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=on';
EXPLAIN SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0); EXPLAIN SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 1 PRIMARY t1 ALL NULL NULL NULL NULL 2
...@@ -1237,7 +1250,7 @@ i ...@@ -1237,7 +1250,7 @@ i
3 3
4 4
set @save_optimizer_switch=@@optimizer_switch; set @save_optimizer_switch=@@optimizer_switch;
set session optimizer_switch='materialization=off'; set session optimizer_switch='materialization=off,in_to_exists=on';
select * from t1 where t1.i in (select t2.i from t2 join t3 where t2.i + t3.i = 5); select * from t1 where t1.i in (select t2.i from t2 join t3 where t2.i + t3.i = 5);
i i
1 1
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -48,7 +48,7 @@ insert into t2i select * from t2; ...@@ -48,7 +48,7 @@ insert into t2i select * from t2;
insert into t3i select * from t3; insert into t3i select * from t3;
# force the use of materialization # force the use of materialization
set @@optimizer_switch='semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
/****************************************************************************** /******************************************************************************
* Simple tests. * Simple tests.
...@@ -111,22 +111,22 @@ select * from t1 where (a1, a2) in (select b1, min(b2) from t2i limit 1,1); ...@@ -111,22 +111,22 @@ select * from t1 where (a1, a2) in (select b1, min(b2) from t2i limit 1,1);
# test re-optimization/re-execution with different execution methods # test re-optimization/re-execution with different execution methods
# prepare once, exec with different modes # prepare once, exec with different modes
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=on';
prepare st1 from prepare st1 from
"select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1)"; "select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1)";
set @@optimizer_switch='default,materialization=off'; set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=on';
execute st1; execute st1;
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=on';
execute st1; execute st1;
set @@optimizer_switch='default,materialization=off'; set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=on';
prepare st1 from prepare st1 from
"select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1)"; "select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1)";
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
execute st1; execute st1;
set @@optimizer_switch='default,materialization=off'; set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=on';
execute st1; execute st1;
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
# materialize the result of ORDER BY # materialize the result of ORDER BY
# non-indexed fields # non-indexed fields
...@@ -327,7 +327,7 @@ select * from t1 order by (select col from columns limit 1); ...@@ -327,7 +327,7 @@ select * from t1 order by (select col from columns limit 1);
Test that BLOBs are not materialized (except when arguments of some functions). Test that BLOBs are not materialized (except when arguments of some functions).
*/ */
# force materialization to be always considered # force materialization to be always considered
set @@optimizer_switch='semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
set @prefix_len = 6; set @prefix_len = 6;
# BLOB == 16 (small blobs that could be stored in HEAP tables) # BLOB == 16 (small blobs that could be stored in HEAP tables)
...@@ -680,7 +680,7 @@ insert into t2bit values (b'001', b'101'); ...@@ -680,7 +680,7 @@ insert into t2bit values (b'001', b'101');
insert into t2bit values (b'010', b'110'); insert into t2bit values (b'010', b'110');
insert into t2bit values (b'110', b'111'); insert into t2bit values (b'110', b'111');
set @@optimizer_switch='semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
explain extended select bin(a1), bin(a2) explain extended select bin(a1), bin(a2)
from t1bit from t1bit
...@@ -718,7 +718,7 @@ drop table t1, t2, t3, t1i, t2i, t3i, columns; ...@@ -718,7 +718,7 @@ drop table t1, t2, t3, t1i, t2i, t3i, columns;
/****************************************************************************** /******************************************************************************
* Test the cache of the left operand of IN. * Test the cache of the left operand of IN.
******************************************************************************/ ******************************************************************************/
set @@optimizer_switch='semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
# Test that default values of Cached_item are not used for comparison # Test that default values of Cached_item are not used for comparison
create table t1 (s1 int); create table t1 (s1 int);
...@@ -812,23 +812,28 @@ drop table t2; ...@@ -812,23 +812,28 @@ drop table t2;
create table t1 (a1 int key); create table t1 (a1 int key);
create table t2 (b1 int); create table t2 (b1 int);
insert into t1 values (5); insert into t1 values (5);
-- echo Only the last query returns correct result. Filed as BUG#40037.
# Query with group by, executed via materialization # Query with group by, executed via materialization
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1); explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
select min(a1) from t1 where 7 in (select b1 from t2 group by b1); select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
# Query with group by, executed via IN=>EXISTS # Query with group by, executed via IN=>EXISTS
set @@optimizer_switch='default,materialization=off'; set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=off';
explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1); explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
select min(a1) from t1 where 7 in (select b1 from t2 group by b1); select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
# Executed with materialization # Executed with materialization
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
explain select min(a1) from t1 where 7 in (select b1 from t2);
select min(a1) from t1 where 7 in (select b1 from t2);
# Executed via IN=>EXISTS
set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=off';
explain select min(a1) from t1 where 7 in (select b1 from t2); explain select min(a1) from t1 where 7 in (select b1 from t2);
select min(a1) from t1 where 7 in (select b1 from t2); select min(a1) from t1 where 7 in (select b1 from t2);
# Executed with semi-join. Notice, this time we get a different result (NULL). # Executed with semi-join. Notice, this time we get a different result (NULL).
# This is the only correct result of all four queries. This difference is # This is the only correct result of all five queries. This difference is
# filed as BUG#40037. # filed as BUG#40037.
set @@optimizer_switch='default,materialization=off'; set @@optimizer_switch='materialization=off,in_to_exists=off,semijoin=on';
explain select min(a1) from t1 where 7 in (select b1 from t2); explain select min(a1) from t1 where 7 in (select b1 from t2);
select min(a1) from t1 where 7 in (select b1 from t2); select min(a1) from t1 where 7 in (select b1 from t2);
drop table t1,t2; drop table t1,t2;
...@@ -840,7 +845,7 @@ create table t1 (a char(2), b varchar(10)); ...@@ -840,7 +845,7 @@ create table t1 (a char(2), b varchar(10));
insert into t1 values ('a', 'aaa'); insert into t1 values ('a', 'aaa');
insert into t1 values ('aa', 'aaaa'); insert into t1 values ('aa', 'aaaa');
set @@optimizer_switch='default,semijoin=off'; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
explain select a,b from t1 where b in (select a from t1); explain select a,b from t1 where b in (select a from t1);
select a,b from t1 where b in (select a from t1); select a,b from t1 where b in (select a from t1);
prepare st1 from "select a,b from t1 where b in (select a from t1)"; prepare st1 from "select a,b from t1 where b in (select a from t1)";
...@@ -861,7 +866,7 @@ CREATE TABLE t2 LIKE t1; ...@@ -861,7 +866,7 @@ CREATE TABLE t2 LIKE t1;
INSERT INTO t2 VALUES (1, 1.789); INSERT INTO t2 VALUES (1, 1.789);
INSERT INTO t2 VALUES (13, 1.454); INSERT INTO t2 VALUES (13, 1.454);
SET @@optimizer_switch='default,semijoin=on,materialization=on'; SET @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=on';
EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2); EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2); SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
...@@ -883,7 +888,7 @@ INSERT INTO t1 VALUES (1,'o','ffff','ffff','ffoo'),(2,'f','ffff','ffff','ffff'); ...@@ -883,7 +888,7 @@ INSERT INTO t1 VALUES (1,'o','ffff','ffff','ffoo'),(2,'f','ffff','ffff','ffff');
CREATE TABLE t2 LIKE t1; CREATE TABLE t2 LIKE t1;
INSERT INTO t2 VALUES (1,'i','iiii','iiii','iiii'),(2,'f','ffff','ffff','ffff'); INSERT INTO t2 VALUES (1,'i','iiii','iiii','iiii'),(2,'f','ffff','ffff','ffff');
SET @@optimizer_switch='default,semijoin=on,materialization=on'; SET @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=on';
EXPLAIN SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0); EXPLAIN SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0);
SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0); SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0);
SELECT pk FROM t1 WHERE (b,c,d) IN (SELECT b,c,d FROM t2 WHERE pk > 0); SELECT pk FROM t1 WHERE (b,c,d) IN (SELECT b,c,d FROM t2 WHERE pk > 0);
...@@ -900,7 +905,7 @@ create table t3(i int); ...@@ -900,7 +905,7 @@ create table t3(i int);
insert into t3 values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); insert into t3 values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
select * from t1 where t1.i in (select t2.i from t2 join t3 where t2.i + t3.i = 5); select * from t1 where t1.i in (select t2.i from t2 join t3 where t2.i + t3.i = 5);
set @save_optimizer_switch=@@optimizer_switch; set @save_optimizer_switch=@@optimizer_switch;
set session optimizer_switch='materialization=off'; set session optimizer_switch='materialization=off,in_to_exists=on';
select * from t1 where t1.i in (select t2.i from t2 join t3 where t2.i + t3.i = 5); select * from t1 where t1.i in (select t2.i from t2 join t3 where t2.i + t3.i = 5);
set session optimizer_switch=@save_optimizer_switch; set session optimizer_switch=@save_optimizer_switch;
drop table t1, t2, t3; drop table t1, t2, t3;
......
This diff is collapsed.
...@@ -3403,6 +3403,19 @@ int rewrite_to_index_subquery_engine(JOIN *join) ...@@ -3403,6 +3403,19 @@ int rewrite_to_index_subquery_engine(JOIN *join)
/* /*
is this simple IN subquery? is this simple IN subquery?
*/ */
/* TODO: In order to use these more efficient subquery engines in more cases,
the following problems need to be solved:
- the code that removes GROUP BY (group_list), also adds an ORDER BY
(order), thus GROUP BY queries (almost?) never pass through this branch.
Solution: remove the test below '!join->order', because we remove the
ORDER clase for subqueries anyway.
- in order to set a more efficient engine, the optimizer needs to both
decide to remove GROUP BY, *and* select one of the JT_[EQ_]REF[_OR_NULL]
access methods, *and* loose scan should be more expensive or
inapliccable. When is that possible?
- Consider expanding the applicability of this rewrite for loose scan
for group by queries.
*/
if (!join->group_list && !join->order && if (!join->group_list && !join->order &&
join->unit->item && join->unit->item &&
join->unit->item->substype() == Item_subselect::IN_SUBS && join->unit->item->substype() == Item_subselect::IN_SUBS &&
......
...@@ -19372,12 +19372,6 @@ int JOIN::reoptimize(Item *added_where, table_map join_tables, ...@@ -19372,12 +19372,6 @@ int JOIN::reoptimize(Item *added_where, table_map join_tables,
DYNAMIC_ARRAY added_keyuse; DYNAMIC_ARRAY added_keyuse;
SARGABLE_PARAM *sargables= 0; /* Used only as a dummy parameter. */ SARGABLE_PARAM *sargables= 0; /* Used only as a dummy parameter. */
if (my_init_dynamic_array(&added_keyuse, sizeof(KEYUSE), 20, 64))
{
delete_dynamic(&added_keyuse);
return 1;
}
/* Re-run the REF optimizer to take into account the new conditions. */ /* Re-run the REF optimizer to take into account the new conditions. */
if (update_ref_and_keys(thd, &added_keyuse, join_tab, tables, added_where, if (update_ref_and_keys(thd, &added_keyuse, join_tab, tables, added_where,
~outer_join, select_lex, &sargables)) ~outer_join, select_lex, &sargables))
......
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