Commit 3a9edc5f authored by Sergey Petrunya's avatar Sergey Petrunya

Merge

parents 962bff5d f84dbf4b
......@@ -5201,8 +5201,8 @@ INSERT INTO t2 VALUES (12,2);
INSERT INTO t2 VALUES (15,4);
EXPLAIN SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 3 Start temporary
1 PRIMARY t2 index NULL PRIMARY 4 NULL 3 Using index; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 3
1 PRIMARY t2 index NULL PRIMARY 4 NULL 3 Using index; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY it eq_ref PRIMARY PRIMARY 4 test.t1.pk 1 Using index; End temporary
SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1);
pk i
......
......@@ -1048,8 +1048,8 @@ explain
select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY X ALL NULL NULL NULL NULL 2
2 DEPENDENT SUBQUERY Y ALL NULL NULL NULL NULL 2 Using where; Start temporary
2 DEPENDENT SUBQUERY Z ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join)
2 DEPENDENT SUBQUERY Y ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY Z ALL NULL NULL NULL NULL 2 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
subq
NULL
......@@ -1193,27 +1193,27 @@ insert into t3 select * from t1;
insert into t3 values (1),(2);
explain select * from t2 where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
explain select * from t2 where a in (select a from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
explain select * from t2 where a in (select a from t3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
explain select * from t1 where a in (select a from t3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Start temporary
1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
drop table t1, t2, t3;
create table t1 (a decimal);
insert into t1 values (1),(2);
explain select * from t1 where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
drop table t1;
set @@optimizer_switch=@save_optimizer_switch;
set @@optimizer_switch=@save_optimizer_switch;
......@@ -1225,8 +1225,8 @@ create table t3 (a int, b int, filler char(100), key(a));
insert into t3 select A.a + 10*B.a, A.a + 10*B.a, 'filler' from t1 A, t1 B, t1 C;
explain select * from t1, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30) and t1.a =3;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where; Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY t3 ref a a 5 test.t2.a 10 End temporary
explain select straight_join * from t1 A, t1 B where A.a in (select a from t2);
id select_type table type possible_keys key key_len ref rows Extra
......@@ -1286,14 +1286,14 @@ insert into t2 select A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B;
set @@optimizer_switch='firstmatch=off,materialization=off';
explain select * from t1 where (a,b) in (select a,b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
set @save_optimizer_search_depth=@@optimizer_search_depth;
set @@optimizer_search_depth=63;
explain select * from t1 where (a,b) in (select a,b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
set @@optimizer_search_depth=@save_optimizer_search_depth;
set @@optimizer_switch=@save_optimizer_switch;
drop table t0, t1, t2;
......@@ -1304,8 +1304,8 @@ create table t1 as select * from t0;
insert into t1 select * from t0;
explain select * from t0 where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t0 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
select * from t0 where a in (select a from t1);
a
10.24
......@@ -1317,8 +1317,8 @@ create table t1 as select * from t0;
insert into t1 select * from t0;
explain select * from t0 where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t0 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
select * from t0 where a in (select a from t1);
a
2008-01-01
......@@ -1331,8 +1331,8 @@ create table t2 as select a as a, a as b from t0 where a < 3;
insert into t2 select * from t2;
explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Start temporary
1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
drop table t0,t1,t2;
......
......@@ -1057,8 +1057,8 @@ explain
select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY X ALL NULL NULL NULL NULL 2
2 DEPENDENT SUBQUERY Y ALL NULL NULL NULL NULL 2 Using where; Start temporary
2 DEPENDENT SUBQUERY Z hash_ALL NULL #hash#$hj 5 test.Y.a 2 Using where; End temporary; Using join buffer (flat, BNLH join)
2 DEPENDENT SUBQUERY Y ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY Z hash_ALL NULL #hash#$hj 5 test.Y.a 2 Using where; Start temporary; End temporary; Using join buffer (flat, BNLH join)
select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
subq
NULL
......@@ -1202,27 +1202,27 @@ insert into t3 select * from t1;
insert into t3 values (1),(2);
explain select * from t2 where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Start temporary
1 PRIMARY t1 hash_ALL NULL #hash#$hj 4 test.t2.a 4 Using where; End temporary; Using join buffer (flat, BNLH join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY t1 hash_ALL NULL #hash#$hj 4 test.t2.a 4 Using where; Start temporary; End temporary; Using join buffer (flat, BNLH join)
explain select * from t2 where a in (select a from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Start temporary
1 PRIMARY t2 hash_ALL NULL #hash#$hj 5 test.t2.a 2 Using where; End temporary; Using join buffer (flat, BNLH join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY t2 hash_ALL NULL #hash#$hj 5 test.t2.a 2 Using where; Start temporary; End temporary; Using join buffer (flat, BNLH join)
explain select * from t2 where a in (select a from t3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
explain select * from t1 where a in (select a from t3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Start temporary
1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
drop table t1, t2, t3;
create table t1 (a decimal);
insert into t1 values (1),(2);
explain select * from t1 where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where; Start temporary
1 PRIMARY t1 hash_ALL NULL #hash#$hj 6 test.t1.a 2 Using where; End temporary; Using join buffer (flat, BNLH join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY t1 hash_ALL NULL #hash#$hj 6 test.t1.a 2 Using where; Start temporary; End temporary; Using join buffer (flat, BNLH join)
drop table t1;
set @@optimizer_switch=@save_optimizer_switch;
set @@optimizer_switch=@save_optimizer_switch;
......@@ -1234,8 +1234,8 @@ create table t3 (a int, b int, filler char(100), key(a));
insert into t3 select A.a + 10*B.a, A.a + 10*B.a, 'filler' from t1 A, t1 B, t1 C;
explain select * from t1, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30) and t1.a =3;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where; Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY t3 ref a a 5 test.t2.a 10 End temporary; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan
explain select straight_join * from t1 A, t1 B where A.a in (select a from t2);
id select_type table type possible_keys key key_len ref rows Extra
......@@ -1295,14 +1295,14 @@ insert into t2 select A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B;
set @@optimizer_switch='firstmatch=off,materialization=off';
explain select * from t1 where (a,b) in (select a,b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where; Start temporary
1 PRIMARY t2 hash_ALL NULL #hash#$hj 10 test.t1.a,test.t1.b 100 Using where; End temporary; Using join buffer (flat, BNLH join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where
1 PRIMARY t2 hash_ALL NULL #hash#$hj 10 test.t1.a,test.t1.b 100 Using where; Start temporary; End temporary; Using join buffer (flat, BNLH join)
set @save_optimizer_search_depth=@@optimizer_search_depth;
set @@optimizer_search_depth=63;
explain select * from t1 where (a,b) in (select a,b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where; Start temporary
1 PRIMARY t2 hash_ALL NULL #hash#$hj 10 test.t1.a,test.t1.b 100 Using where; End temporary; Using join buffer (flat, BNLH join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where
1 PRIMARY t2 hash_ALL NULL #hash#$hj 10 test.t1.a,test.t1.b 100 Using where; Start temporary; End temporary; Using join buffer (flat, BNLH join)
set @@optimizer_search_depth=@save_optimizer_search_depth;
set @@optimizer_switch=@save_optimizer_switch;
drop table t0, t1, t2;
......@@ -1313,8 +1313,8 @@ create table t1 as select * from t0;
insert into t1 select * from t0;
explain select * from t0 where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Using where; Start temporary
1 PRIMARY t1 hash_ALL NULL #hash#$hj 3 test.t0.a 4 Using where; End temporary; Using join buffer (flat, BNLH join)
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY t1 hash_ALL NULL #hash#$hj 3 test.t0.a 4 Using where; Start temporary; End temporary; Using join buffer (flat, BNLH join)
select * from t0 where a in (select a from t1);
a
10.24
......@@ -1326,8 +1326,8 @@ create table t1 as select * from t0;
insert into t1 select * from t0;
explain select * from t0 where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Using where; Start temporary
1 PRIMARY t1 hash_ALL NULL #hash#$hj 4 test.t0.a 4 Using where; End temporary; Using join buffer (flat, BNLH join)
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY t1 hash_ALL NULL #hash#$hj 4 test.t0.a 4 Using where; Start temporary; End temporary; Using join buffer (flat, BNLH join)
select * from t0 where a in (select a from t1);
a
2008-01-01
......@@ -1340,8 +1340,8 @@ create table t2 as select a as a, a as b from t0 where a < 3;
insert into t2 select * from t2;
explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Start temporary
1 PRIMARY X hash_ALL NULL #hash#$hj 5 test.t1.a 6 Using where; Using join buffer (flat, BNLH join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
1 PRIMARY X hash_ALL NULL #hash#$hj 5 test.t1.a 6 Using where; Start temporary; Using join buffer (flat, BNLH join)
1 PRIMARY Y hash_ALL NULL #hash#$hj 5 test.t1.b 6 Using where; Using join buffer (incremental, BNLH join)
1 PRIMARY Z hash_ALL NULL #hash#$hj 5 test.t1.c 6 Using where; End temporary; Using join buffer (incremental, BNLH join)
drop table t0,t1,t2;
......
......@@ -15,16 +15,16 @@ insert into t2 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1');
flush tables;
EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY OUTR ALL NULL NULL NULL NULL 2 Using where; Start temporary
1 PRIMARY INNR ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY OUTR ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY INNR ALL NULL NULL NULL NULL 2 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
flush tables;
SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL );
dt
flush tables;
EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY OUTR ALL NULL NULL NULL NULL 2 Using where; Start temporary
1 PRIMARY INNR ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY OUTR ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY INNR ALL NULL NULL NULL NULL 2 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
flush tables;
SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
dt
......@@ -67,8 +67,8 @@ explain extended
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Start temporary
1 PRIMARY x1 ALL NULL NULL NULL NULL 2 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
1 PRIMARY x1 ALL NULL NULL NULL NULL 2 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1276 Field or reference 'test.t1.cur_date' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`cur_date` AS `cur_date` from `test`.`t1` semi join (`test`.`t1` `x1`) where ((`test`.`x1`.`id` = `test`.`t1`.`id`) and (`test`.`t1`.`cur_date` = 0))
......@@ -79,8 +79,8 @@ explain extended
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Start temporary
1 PRIMARY x1 ALL NULL NULL NULL NULL 2 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
1 PRIMARY x1 ALL NULL NULL NULL NULL 2 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1276 Field or reference 'test.t2.cur_date' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t2`.`id` AS `id`,`test`.`t2`.`cur_date` AS `cur_date` from `test`.`t2` semi join (`test`.`t2` `x1`) where ((`test`.`x1`.`id` = `test`.`t2`.`id`) and (`test`.`t2`.`cur_date` = 0))
......
......@@ -5154,8 +5154,8 @@ explain SELECT * FROM ot1,ot4
WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot1 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
1 PRIMARY ot1 ALL NULL NULL NULL NULL 2
1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; End temporary; Using join buffer (flat, BNL join)
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
......@@ -5200,8 +5200,8 @@ INSERT INTO t2 VALUES (12,2);
INSERT INTO t2 VALUES (15,4);
EXPLAIN SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 3 Start temporary
1 PRIMARY t2 index NULL PRIMARY 4 NULL 3 Using index; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 3
1 PRIMARY t2 index NULL PRIMARY 4 NULL 3 Using index; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY it eq_ref PRIMARY PRIMARY 4 test.t1.pk 1 Using index; End temporary
SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1);
pk i
......
......@@ -5205,8 +5205,8 @@ INSERT INTO t2 VALUES (12,2);
INSERT INTO t2 VALUES (15,4);
EXPLAIN SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 3 Start temporary
1 PRIMARY t2 index NULL PRIMARY 4 NULL 3 Using index; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 3
1 PRIMARY t2 index NULL PRIMARY 4 NULL 3 Using index; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY it eq_ref PRIMARY PRIMARY 4 test.t1.pk 1 Using index; End temporary
SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1);
pk i
......
......@@ -1242,8 +1242,8 @@ A.t1field IN (SELECT A.t1field FROM t2 B) AND
A.t1field IN (SELECT C.t2field FROM t2 C
WHERE C.t2field IN (SELECT D.t2field FROM t2 D));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY A index PRIMARY PRIMARY 4 NULL 3 Using index; Start temporary
1 PRIMARY B index NULL PRIMARY 4 NULL 3 Using index; End temporary
1 PRIMARY A index PRIMARY PRIMARY 4 NULL 3 Using index
1 PRIMARY B index NULL PRIMARY 4 NULL 3 Using index; Start temporary; End temporary
1 PRIMARY C eq_ref PRIMARY PRIMARY 4 test.A.t1field 1 Using index
1 PRIMARY D eq_ref PRIMARY PRIMARY 4 test.A.t1field 1 Using index
SELECT * FROM t1 A
......@@ -1439,8 +1439,8 @@ set optimizer_switch='firstmatch=off,loosescan=off,materialization=off';
explain
select * from t0 where a in (select t1.a from t1 left join t2 on t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
1 PRIMARY t0 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; End temporary
select * from t0 where a in (select t1.a from t1 left join t2 on t1.a=t2.a);
a
......@@ -1498,8 +1498,8 @@ explain
select * from t0
where a in (select t1.a from t1 left join (t3 join t2 on t3.b=t2.b) on t1.a=t3.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
1 PRIMARY t0 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Start temporary
1 PRIMARY t3 ALL NULL NULL NULL NULL 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; End temporary
select * from t0
......@@ -1516,8 +1516,8 @@ explain
select * from t0
where a in (select t1.a from t1 left join (t3 join t2 on t3.b=t2.b) on t1.a=t3.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
1 PRIMARY t0 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; End temporary
select * from t0
......@@ -1711,10 +1711,10 @@ INSERT INTO t4 VALUES (0),(NULL);
explain
SELECT * FROM t1 NATURAL LEFT JOIN (t2, t3) WHERE IFNULL(t2.f3,'foo') IN (SELECT * FROM t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY t3 ALL NULL NULL NULL NULL 5 Using where
1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; End temporary
1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; Start temporary; End temporary
SELECT * FROM t1 NATURAL LEFT JOIN (t2, t3 ) WHERE IFNULL(t2.f3,'foo') IN (SELECT * FROM t4);
f1 f2 f3 f3
2 0 0 0
......@@ -1772,9 +1772,9 @@ INSERT INTO t3 VALUES (6,5),(6,2),(8,0),(9,1),(6,5);
explain
SELECT * FROM t1, t2 WHERE (t2.a , t1.b) IN (SELECT a, b FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 2 Using index; Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL b NULL NULL NULL 5 Using where; End temporary
1 PRIMARY t3 ALL b NULL NULL NULL 5 Using where; Start temporary; End temporary
SELECT * FROM t1, t2 WHERE (t2.a , t1.b) IN (SELECT a, b FROM t3);
b a
5 6
......@@ -1877,10 +1877,10 @@ alias1.c IN (SELECT SQ3_alias1.b
FROM t2 AS SQ3_alias1 STRAIGHT_JOIN t2 AS SQ3_alias2)
LIMIT 100;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 20 Start temporary
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 20
1 PRIMARY alias2 ALL NULL NULL NULL NULL 20 Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 20 Using join buffer (flat, BNL join)
1 PRIMARY SQ3_alias1 ALL NULL NULL NULL NULL 20 Using where
1 PRIMARY SQ3_alias1 ALL NULL NULL NULL NULL 20 Using where; Start temporary
1 PRIMARY SQ3_alias2 index NULL PRIMARY 4 NULL 20 Using index; End temporary
2 DERIVED t2 ALL NULL NULL NULL NULL 20
create table t3 as
......@@ -2040,8 +2040,8 @@ set optimizer_switch='semijoin_with_cache=on';
explain
select * from t1 where t1.a in (select t2.a from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
select * from t1 where t1.a in (select t2.a from t2);
a
1
......@@ -2050,8 +2050,8 @@ set optimizer_switch='semijoin_with_cache=off';
explain
select * from t1 where t1.a in (select t2.a from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; End temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Start temporary; End temporary
select * from t1 where t1.a in (select t2.a from t2);
a
1
......
set @subselect_sj2_tmp= @@optimizer_switch;
set optimizer_switch='semijoin=on,firstmatch=on,loosescan=on';
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
drop table if exists t0, t1, t2, t3;
drop table if exists t0, t1, t2, t3, t4, t5;
drop view if exists v1;
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
......@@ -331,8 +331,8 @@ WHERE Language='English' AND Percentage > 10 AND
t2.Population > 100000);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 range Population,Country Population 4 NULL 1 Using index condition; Rowid-ordered scan; Start temporary
1 PRIMARY t2 eq_ref PRIMARY,Population PRIMARY 3 test.t1.Country 1 Using where
1 PRIMARY t3 eq_ref PRIMARY,Percentage PRIMARY 33 test.t1.Country,const 1 Using index condition; Using where; End temporary
1 PRIMARY t2 eq_ref PRIMARY,Population PRIMARY 3 test.t1.Country 1 Using where; End temporary
1 PRIMARY t3 eq_ref PRIMARY,Percentage PRIMARY 33 test.t1.Country,const 1 Using index condition; Using where
set optimizer_switch=@bug35674_save_optimizer_switch;
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (
......
......@@ -10,7 +10,7 @@ join_cache_level 6
set @subselect_sj2_tmp= @@optimizer_switch;
set optimizer_switch='semijoin=on,firstmatch=on,loosescan=on';
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
drop table if exists t0, t1, t2, t3;
drop table if exists t0, t1, t2, t3, t4, t5;
drop view if exists v1;
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
......@@ -340,8 +340,8 @@ WHERE Language='English' AND Percentage > 10 AND
t2.Population > 100000);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 range Population,Country Population 4 NULL 1 Using index condition; Rowid-ordered scan; Start temporary
1 PRIMARY t2 eq_ref PRIMARY,Population PRIMARY 3 test.t1.Country 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
1 PRIMARY t3 eq_ref PRIMARY,Percentage PRIMARY 33 test.t1.Country,const 1 Using index condition; Using where; End temporary; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan
1 PRIMARY t2 eq_ref PRIMARY,Population PRIMARY 3 test.t1.Country 1 Using where; End temporary; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
1 PRIMARY t3 eq_ref PRIMARY,Percentage PRIMARY 33 test.t1.Country,const 1 Using index condition; Using where; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan
set optimizer_switch=@bug35674_save_optimizer_switch;
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (
......
......@@ -3,7 +3,7 @@ set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
set @subselect_sj2_tmp= @@optimizer_switch;
set optimizer_switch='semijoin=on,firstmatch=on,loosescan=on';
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
drop table if exists t0, t1, t2, t3;
drop table if exists t0, t1, t2, t3, t4, t5;
drop view if exists v1;
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
......@@ -333,8 +333,8 @@ WHERE Language='English' AND Percentage > 10 AND
t2.Population > 100000);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 range Population,Country Population 4 NULL 1 Using index condition; Rowid-ordered scan; Start temporary
1 PRIMARY t2 eq_ref PRIMARY,Population PRIMARY 3 test.t1.Country 1 Using where
1 PRIMARY t3 eq_ref PRIMARY,Percentage PRIMARY 33 test.t1.Country,const 1 Using index condition; Using where; End temporary
1 PRIMARY t2 eq_ref PRIMARY,Population PRIMARY 3 test.t1.Country 1 Using where; End temporary
1 PRIMARY t3 eq_ref PRIMARY,Percentage PRIMARY 33 test.t1.Country,const 1 Using index condition; Using where
set optimizer_switch=@bug35674_save_optimizer_switch;
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (
......
drop table if exists t1,t2,t3,t4;
#
# BUG#887468: Second assertion `keypart_map' failed in maria_rkey with semijoin
#
CREATE TABLE t1 (
pk int(11) NOT NULL AUTO_INCREMENT,
col_int_key int(11) DEFAULT NULL,
col_varchar_key varchar(1) DEFAULT NULL,
dummy char(30),
PRIMARY KEY (pk),
KEY col_varchar_key (col_varchar_key,col_int_key)
) ENGINE=Aria AUTO_INCREMENT=30 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO t1 (pk, col_varchar_key, col_int_key) VALUES
(10,NULL,0), (11,'d',4), (12,'g',8), (13,'x',NULL), (14,'f',NULL),
(15,'p',0), (16,'j',NULL), (17,'c',8), (18,'z',8), (19,'j',6), (20,NULL,2),
(21,'p',3), (22,'w',1), (23,'c',NULL), (24,'j',1), (25,'f',10), (26,'v',2),
(27,'f',103), (28,'q',3), (29,'y',6);
CREATE TABLE t2 (
pk int(11) NOT NULL AUTO_INCREMENT,
col_int_key int(11) DEFAULT NULL,
dummy char(36),
PRIMARY KEY (pk),
KEY col_int_key (col_int_key)
) ENGINE=Aria AUTO_INCREMENT=101 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO t2 ( pk, col_int_key) VALUES
(1,8), (2,2), (3,9), (4,6), (5,NULL), (6,NULL), (7,48), (8,228), (9,3), (10,5),
(11,39), (12,6), (13,8), (14,3), (15,NULL), (16,2), (17,6), (18,3), (19,1), (20,4),
(21,3), (22,1), (23,NULL), (24,97), (25,0), (26,0), (27,9), (28,5), (29,9), (30,0),
(31,2), (32,172), (33,NULL), (34,5), (35,119), (36,1), (37,4), (38,8), (39,NULL), (40,6),
(41,5), (42,5), (43,1), (44,7), (45,2), (46,8), (47,9), (48,NULL), (49,NULL), (50,3),
(51,172), (52,NULL), (53,6), (54,6), (55,5), (56,4), (57,3), (58,2), (59,7), (60,4),
(61,6), (62,0), (63,8), (64,5), (65,8), (66,2), (67,9), (68,7), (69,5), (70,7),
(71,0), (72,4), (73,3), (74,1), (75,0), (76,6), (77,2), (78,NULL), (79,8), (80,NULL),
(81,NULL), (82,NULL), (83,3), (84,7), (85,3), (86,5), (87,5), (88,1), (89,2), (90,1),
(91,7), (92,1), (93,9), (94,9), (95,8), (96,3), (97,7), (98,4), (99,9), (100,0);
CREATE TABLE t3 (
pk int(11) NOT NULL AUTO_INCREMENT,
dummy char(34),
col_varchar_key varchar(1) DEFAULT NULL,
col_int_key int(11) DEFAULT NULL,
PRIMARY KEY (pk),
KEY col_varchar_key (col_varchar_key,col_int_key)
) ENGINE=Aria AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO t3 (pk, col_varchar_key) VALUES (1,'v'), (2,'c'), (3,NULL);
CREATE TABLE t4 (
pk int(11) NOT NULL AUTO_INCREMENT,
dummy char (38),
PRIMARY KEY (pk)
) ENGINE=Aria AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO t4 (pk) VALUES (1), (2), (3);
SELECT *
FROM t1
JOIN t2
ON ( t2.col_int_key = t1.pk )
WHERE t1.col_varchar_key IN (
SELECT t3.col_varchar_key FROM t3, t4
);
pk col_int_key col_varchar_key dummy pk col_int_key dummy
drop table t1, t2, t3, t4;
......@@ -1253,8 +1253,8 @@ A.t1field IN (SELECT A.t1field FROM t2 B) AND
A.t1field IN (SELECT C.t2field FROM t2 C
WHERE C.t2field IN (SELECT D.t2field FROM t2 D));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY A index PRIMARY PRIMARY 4 NULL 3 Using index; Start temporary
1 PRIMARY B index NULL PRIMARY 4 NULL 3 Using index; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY A index PRIMARY PRIMARY 4 NULL 3 Using index
1 PRIMARY B index NULL PRIMARY 4 NULL 3 Using index; Start temporary; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY C eq_ref PRIMARY PRIMARY 4 test.A.t1field 1 Using index
1 PRIMARY D eq_ref PRIMARY PRIMARY 4 test.A.t1field 1 Using index
SELECT * FROM t1 A
......@@ -1450,8 +1450,8 @@ set optimizer_switch='firstmatch=off,loosescan=off,materialization=off';
explain
select * from t0 where a in (select t1.a from t1 left join t2 on t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t0 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; End temporary; Using join buffer (incremental, BNL join)
select * from t0 where a in (select t1.a from t1 left join t2 on t1.a=t2.a);
a
......@@ -1509,8 +1509,8 @@ explain
select * from t0
where a in (select t1.a from t1 left join (t3 join t2 on t3.b=t2.b) on t1.a=t3.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t0 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; End temporary; Using join buffer (incremental, BNL join)
select * from t0
......@@ -1527,8 +1527,8 @@ explain
select * from t0
where a in (select t1.a from t1 left join (t3 join t2 on t3.b=t2.b) on t1.a=t3.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t0 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using join buffer (incremental, BNL join)
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (incremental, BNL join)
select * from t0
......@@ -1722,10 +1722,10 @@ INSERT INTO t4 VALUES (0),(NULL);
explain
SELECT * FROM t1 NATURAL LEFT JOIN (t2, t3) WHERE IFNULL(t2.f3,'foo') IN (SELECT * FROM t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (incremental, BNL join)
1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (incremental, BNL join)
1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; Start temporary; End temporary; Using join buffer (incremental, BNL join)
SELECT * FROM t1 NATURAL LEFT JOIN (t2, t3 ) WHERE IFNULL(t2.f3,'foo') IN (SELECT * FROM t4);
f1 f2 f3 f3
2 0 0 0
......@@ -1783,9 +1783,9 @@ INSERT INTO t3 VALUES (6,5),(6,2),(8,0),(9,1),(6,5);
explain
SELECT * FROM t1, t2 WHERE (t2.a , t1.b) IN (SELECT a, b FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 2 Using index; Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL b NULL NULL NULL 5 Using where; End temporary; Using join buffer (incremental, BNL join)
1 PRIMARY t3 ALL b NULL NULL NULL 5 Using where; Start temporary; End temporary; Using join buffer (incremental, BNL join)
SELECT * FROM t1, t2 WHERE (t2.a , t1.b) IN (SELECT a, b FROM t3);
b a
5 6
......@@ -1888,10 +1888,10 @@ alias1.c IN (SELECT SQ3_alias1.b
FROM t2 AS SQ3_alias1 STRAIGHT_JOIN t2 AS SQ3_alias2)
LIMIT 100;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 20 Start temporary
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 20
1 PRIMARY alias2 ALL NULL NULL NULL NULL 20 Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 20 Using join buffer (incremental, BNL join)
1 PRIMARY SQ3_alias1 ALL NULL NULL NULL NULL 20 Using where; Using join buffer (incremental, BNL join)
1 PRIMARY SQ3_alias1 ALL NULL NULL NULL NULL 20 Using where; Start temporary; Using join buffer (incremental, BNL join)
1 PRIMARY SQ3_alias2 index NULL PRIMARY 4 NULL 20 Using index; End temporary; Using join buffer (incremental, BNL join)
2 DERIVED t2 ALL NULL NULL NULL NULL 20
create table t3 as
......@@ -2051,8 +2051,8 @@ set optimizer_switch='semijoin_with_cache=on';
explain
select * from t1 where t1.a in (select t2.a from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
select * from t1 where t1.a in (select t2.a from t2);
a
1
......@@ -2061,8 +2061,8 @@ set optimizer_switch='semijoin_with_cache=off';
explain
select * from t1 where t1.a in (select t2.a from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; End temporary
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Start temporary; End temporary
select * from t1 where t1.a in (select t2.a from t2);
a
1
......@@ -2123,8 +2123,8 @@ explain
SELECT * FROM t0 WHERE t0.a IN
(SELECT t1.a FROM t1, t2 WHERE t2.a=t0.a AND t1.b=t2.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 5 Using where; Start temporary
1 PRIMARY t1 ref a a 5 test.t0.a 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
1 PRIMARY t0 ALL NULL NULL NULL NULL 5 Using where
1 PRIMARY t1 ref a a 5 test.t0.a 1 Start temporary; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t0.a 1 Using where; End temporary; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan
SELECT * FROM t0 WHERE t0.a IN
(SELECT t1.a FROM t1, t2 WHERE t2.a=t0.a AND t1.b=t2.b);
......@@ -2156,8 +2156,8 @@ EXPLAIN
SELECT * FROM t1, t2
WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t3 ALL d NULL NULL NULL 5 Range checked for each record (index map: 0x2)
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t3 ALL d NULL NULL NULL 5 Range checked for each record (index map: 0x2); Start temporary
1 PRIMARY t2 hash_ALL PRIMARY #hash#PRIMARY 4 test.t3.b 4 End temporary; Using join buffer (flat, BNLH join)
SELECT * FROM t1, t2
WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
......@@ -2171,8 +2171,8 @@ EXPLAIN
SELECT * FROM t1, t2
WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
1 PRIMARY t3 ALL d NULL NULL NULL 5 Range checked for each record (index map: 0x2)
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t3 ALL d NULL NULL NULL 5 Range checked for each record (index map: 0x2); Start temporary
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t3.b 1 End temporary; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
SELECT * FROM t1, t2
WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
......
......@@ -297,11 +297,11 @@ where (a1, a2) in (select b1, b2 from t2 where b1 > '0') and
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 18 func,func 1 100.00
1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 18 func,func 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 18 func,func 1 100.00
3 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
3 SUBQUERY t2i index it2i1,it2i2,it2i3 it2i3 18 NULL 5 80.00 Using where; Using index; Using join buffer (flat, BNL join)
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3`) where ((`test`.`t2i`.`b2` = `test`.`t3`.`c2`) and (`test`.`t2i`.`b1` = `test`.`t3`.`c1`) and (`test`.`t2`.`b1` > '0') and (`test`.`t3`.`c2` > '0'))
select * from t1
......@@ -317,14 +317,12 @@ where (a1, a2) in (select b1, b2 from t2i where b1 > '0') and
(a1, a2) in (select c1, c2 from t3i
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1i index it1i1,it1i2,it1i3 # # # 3 100.00 #
1 PRIMARY <subquery2> eq_ref distinct_key # # # 1 100.00 #
1 PRIMARY <subquery3> eq_ref distinct_key # # # 1 100.00 #
2 SUBQUERY t2i index it2i1,it2i2,it2i3 # # # 5 100.00 #
3 SUBQUERY t2i index it2i1,it2i2,it2i3 # # # 5 100.00 #
3 SUBQUERY t3i index it3i1,it3i2,it3i3 # # # 4 75.00 #
1 PRIMARY t2i index it2i1,it2i2,it2i3 # # # 5 40.00 #
1 PRIMARY t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 #
1 PRIMARY t3i ref it3i1,it3i2,it3i3 # # # 1 100.00 #
1 PRIMARY t2i ref it2i1,it2i2,it2i3 # # # 2 100.00 #
Warnings:
Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` semi join (`test`.`t2i`) semi join (`test`.`t2i` join `test`.`t3i`) where ((`test`.`t3i`.`c2` = `test`.`t2i`.`b2`) and (`test`.`t3i`.`c1` = `test`.`t2i`.`b1`) and (`test`.`t2i`.`b1` > '0') and (`test`.`t2i`.`b2` > '0'))
Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` semi join (`test`.`t2i`) semi join (`test`.`t2i` join `test`.`t3i`) where ((`test`.`t1i`.`a2` = `test`.`t2i`.`b2`) and (`test`.`t3i`.`c2` = `test`.`t2i`.`b2`) and (`test`.`t2i`.`b2` = `test`.`t2i`.`b2`) and (`test`.`t1i`.`a1` = `test`.`t2i`.`b1`) and (`test`.`t3i`.`c1` = `test`.`t2i`.`b1`) and (`test`.`t2i`.`b1` = `test`.`t2i`.`b1`) and (`test`.`t2i`.`b1` > '0') and (`test`.`t2i`.`b2` > '0'))
select * from t1i
where (a1, a2) in (select b1, b2 from t2i where b1 > '0') and
(a1, a2) in (select c1, c2 from t3i
......@@ -341,11 +339,11 @@ b2 in (select c2 from t3 where c2 LIKE '%03')) and
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 18 func,func 1 100.00
1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 18 func,func 1 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 18 func,func 1 100.00
5 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
5 SUBQUERY t2i index it2i1,it2i2,it2i3 it2i3 18 NULL 5 80.00 Using where; Using index; Using join buffer (flat, BNL join)
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
3 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
......@@ -366,16 +364,16 @@ b2 in (select c2 from t3 t3b where c2 LIKE '%03')) and
(a1, a2) in (select c1, c2 from t3 t3c
where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 18 func,func 1 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
5 SUBQUERY t3c ALL NULL NULL NULL NULL 4 100.00 Using where
5 SUBQUERY t2i index it2i1,it2i2,it2i3 it2i3 18 NULL 5 80.00 Using where; Using index; Using join buffer (flat, BNL join)
4 SUBQUERY t3b ALL NULL NULL NULL NULL 4 100.00 Using where
3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3` `t3c`) where ((`test`.`t2`.`b2` = `test`.`t1`.`a2`) and (`test`.`t2i`.`b2` = `test`.`t3c`.`c2`) and (`test`.`t2`.`b1` = `test`.`t1`.`a1`) and (`test`.`t2i`.`b1` = `test`.`t3c`.`c1`) and (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `<subquery4>`.`c2`))))))) and (`test`.`t3c`.`c2` > '0'))
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3` `t3c`) where ((`test`.`t2i`.`b2` = `test`.`t3c`.`c2`) and (`test`.`t2`.`b2` = `test`.`t1`.`a2`) and (`test`.`t2i`.`b1` = `test`.`t3c`.`c1`) and (`test`.`t2`.`b1` = `test`.`t1`.`a1`) and (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `<subquery4>`.`c2`))))))) and (`test`.`t3c`.`c2` > '0'))
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 t3a where c1 = a1) or
......@@ -406,15 +404,13 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t2 ALL NULL # # # 5 100.00 #
4 SUBQUERY t3 ALL NULL # # # 4 100.00 #
3 SUBQUERY t3 ALL NULL # # # 4 100.00 #
7 UNION t1i index it1i1,it1i2,it1i3 # # # 3 100.00 #
7 UNION <subquery8> eq_ref distinct_key # # # 1 100.00 #
7 UNION <subquery9> eq_ref distinct_key # # # 1 100.00 #
8 SUBQUERY t2i index it2i1,it2i2,it2i3 # # # 5 100.00 #
9 SUBQUERY t2i index it2i1,it2i2,it2i3 # # # 5 100.00 #
9 SUBQUERY t3i index it3i1,it3i2,it3i3 # # # 4 75.00 #
7 UNION t2i index it2i1,it2i2,it2i3 # # # 5 40.00 #
7 UNION t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 #
7 UNION t3i ref it3i1,it3i2,it3i3 # # # 1 100.00 #
7 UNION t2i ref it2i1,it2i2,it2i3 # # # 2 100.00 #
NULL UNION RESULT <union1,7> ALL NULL # # # NULL NULL #
Warnings:
Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where (<expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `<subquery3>`.`c2`)))))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `<subquery4>`.`c2`))))))) group by `test`.`t2`.`b1`,`test`.`t2`.`b2`) semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t1` where ((`test`.`t3`.`c2` = `<subquery2>`.`b2`) and (`test`.`t1`.`a2` = `<subquery2>`.`b2`) and (`test`.`t2i`.`b2` = `<subquery2>`.`b2`) and (`test`.`t3`.`c1` = `<subquery2>`.`b1`) and (`test`.`t1`.`a1` = `<subquery2>`.`b1`) and (`test`.`t2i`.`b1` = `<subquery2>`.`b1`) and (`<subquery2>`.`b2` > '0'))) union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` semi join (`test`.`t2i`) semi join (`test`.`t2i` join `test`.`t3i`) where ((`test`.`t3i`.`c2` = `test`.`t2i`.`b2`) and (`test`.`t3i`.`c1` = `test`.`t2i`.`b1`) and (`test`.`t2i`.`b1` > '0') and (`test`.`t2i`.`b2` > '0')))
Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where (<expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `<subquery3>`.`c2`)))))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `<subquery4>`.`c2`))))))) group by `test`.`t2`.`b1`,`test`.`t2`.`b2`) semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t1` where ((`test`.`t3`.`c2` = `<subquery2>`.`b2`) and (`test`.`t1`.`a2` = `<subquery2>`.`b2`) and (`test`.`t2i`.`b2` = `<subquery2>`.`b2`) and (`test`.`t3`.`c1` = `<subquery2>`.`b1`) and (`test`.`t1`.`a1` = `<subquery2>`.`b1`) and (`test`.`t2i`.`b1` = `<subquery2>`.`b1`) and (`<subquery2>`.`b2` > '0'))) union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` semi join (`test`.`t2i`) semi join (`test`.`t2i` join `test`.`t3i`) where ((`test`.`t1i`.`a2` = `test`.`t2i`.`b2`) and (`test`.`t3i`.`c2` = `test`.`t2i`.`b2`) and (`test`.`t2i`.`b2` = `test`.`t2i`.`b2`) and (`test`.`t1i`.`a1` = `test`.`t2i`.`b1`) and (`test`.`t3i`.`c1` = `test`.`t2i`.`b1`) and (`test`.`t2i`.`b1` = `test`.`t2i`.`b1`) and (`test`.`t2i`.`b1` > '0') and (`test`.`t2i`.`b2` > '0')))
(select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
......@@ -505,16 +501,16 @@ b2 in (select c2 from t3 t3b where c2 LIKE '%03')) and
(a1, a2) in (select c1, c2 from t3 t3c
where (c1, c2) in (select b1, b2 from t2i where b2 > '0' or b2 = a2));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary
1 PRIMARY t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t1.a1,test.t1.a2 2 100.00 Using index
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t1.a1,test.t1.a2 2 100.00 Using index; Start temporary
1 PRIMARY t3c ALL NULL NULL NULL NULL 4 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
4 SUBQUERY t3b ALL NULL NULL NULL NULL 4 100.00 Using where
3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a2' of SELECT #6 was resolved in SELECT #1
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3` `t3c`) where ((`test`.`t2i`.`b2` = `test`.`t1`.`a2`) and (`test`.`t2`.`b2` = `test`.`t1`.`a2`) and (`test`.`t3c`.`c2` = `test`.`t1`.`a2`) and (`test`.`t2i`.`b1` = `test`.`t1`.`a1`) and (`test`.`t2`.`b1` = `test`.`t1`.`a1`) and (`test`.`t3c`.`c1` = `test`.`t1`.`a1`) and (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `<subquery4>`.`c2`))))))))
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3` `t3c`) where ((`test`.`t2`.`b2` = `test`.`t1`.`a2`) and (`test`.`t2i`.`b2` = `test`.`t1`.`a2`) and (`test`.`t3c`.`c2` = `test`.`t1`.`a2`) and (`test`.`t2`.`b1` = `test`.`t1`.`a1`) and (`test`.`t2i`.`b1` = `test`.`t1`.`a1`) and (`test`.`t3c`.`c1` = `test`.`t1`.`a1`) and (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `<subquery4>`.`c2`))))))))
explain extended
select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01');
id select_type table type possible_keys key key_len ref rows filtered Extra
......@@ -617,8 +613,8 @@ explain extended select left(a1,7), left(a2,7)
from t1_16
where a1 in (select b1 from t2_16 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary
1 PRIMARY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` semi join (`test`.`t2_16`) where ((`test`.`t2_16`.`b1` = `test`.`t1_16`.`a1`) and (`test`.`t1_16`.`a1` > '0'))
select left(a1,7), left(a2,7)
......@@ -631,8 +627,8 @@ explain extended select left(a1,7), left(a2,7)
from t1_16
where (a1,a2) in (select b1, b2 from t2_16 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary
1 PRIMARY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` semi join (`test`.`t2_16`) where ((`test`.`t2_16`.`b2` = `test`.`t1_16`.`a2`) and (`test`.`t2_16`.`b1` = `test`.`t1_16`.`a1`) and (`test`.`t1_16`.`a1` > '0'))
select left(a1,7), left(a2,7)
......@@ -695,8 +691,8 @@ where (a1, a2) IN
where t2.b2 = substring(t2_16.b2,1,6) and
t2.b1 IN (select c1 from t3 where c2 > '0')));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Start temporary
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
......@@ -732,8 +728,8 @@ explain extended select left(a1,7), left(a2,7)
from t1_512
where a1 in (select b1 from t2_512 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary
1 PRIMARY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` semi join (`test`.`t2_512`) where ((`test`.`t2_512`.`b1` = `test`.`t1_512`.`a1`) and (`test`.`t1_512`.`a1` > '0'))
select left(a1,7), left(a2,7)
......@@ -746,8 +742,8 @@ explain extended select left(a1,7), left(a2,7)
from t1_512
where (a1,a2) in (select b1, b2 from t2_512 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary
1 PRIMARY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` semi join (`test`.`t2_512`) where ((`test`.`t2_512`.`b2` = `test`.`t1_512`.`a2`) and (`test`.`t2_512`.`b1` = `test`.`t1_512`.`a1`) and (`test`.`t1_512`.`a1` > '0'))
select left(a1,7), left(a2,7)
......@@ -828,8 +824,8 @@ explain extended select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select b1 from t2_1024 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary
1 PRIMARY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` semi join (`test`.`t2_1024`) where ((`test`.`t2_1024`.`b1` = `test`.`t1_1024`.`a1`) and (`test`.`t1_1024`.`a1` > '0'))
select left(a1,7), left(a2,7)
......@@ -842,8 +838,8 @@ explain extended select left(a1,7), left(a2,7)
from t1_1024
where (a1,a2) in (select b1, b2 from t2_1024 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary
1 PRIMARY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` semi join (`test`.`t2_1024`) where ((`test`.`t2_1024`.`b2` = `test`.`t1_1024`.`a2`) and (`test`.`t2_1024`.`b1` = `test`.`t1_1024`.`a1`) and (`test`.`t1_1024`.`a1` > '0'))
select left(a1,7), left(a2,7)
......@@ -856,8 +852,8 @@ explain extended select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select substring(b1,1,1024) from t2_1024 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Start temporary
1 PRIMARY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` semi join (`test`.`t2_1024`) where ((`test`.`t2_1024`.`b1` > '0') and (`test`.`t1_1024`.`a1` = substr(`test`.`t2_1024`.`b1`,1,1024)))
select left(a1,7), left(a2,7)
......@@ -923,8 +919,8 @@ explain extended select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select b1 from t2_1025 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary
1 PRIMARY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` semi join (`test`.`t2_1025`) where ((`test`.`t2_1025`.`b1` = `test`.`t1_1025`.`a1`) and (`test`.`t1_1025`.`a1` > '0'))
select left(a1,7), left(a2,7)
......@@ -937,8 +933,8 @@ explain extended select left(a1,7), left(a2,7)
from t1_1025
where (a1,a2) in (select b1, b2 from t2_1025 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary
1 PRIMARY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` semi join (`test`.`t2_1025`) where ((`test`.`t2_1025`.`b2` = `test`.`t1_1025`.`a2`) and (`test`.`t2_1025`.`b1` = `test`.`t1_1025`.`a1`) and (`test`.`t1_1025`.`a1` > '0'))
select left(a1,7), left(a2,7)
......@@ -951,8 +947,8 @@ explain extended select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select substring(b1,1,1025) from t2_1025 where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Start temporary
1 PRIMARY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` semi join (`test`.`t2_1025`) where ((`test`.`t2_1025`.`b1` > '0') and (`test`.`t1_1025`.`a1` = substr(`test`.`t2_1025`.`b1`,1,1025)))
select left(a1,7), left(a2,7)
......@@ -1025,8 +1021,8 @@ explain extended select bin(a1), a2
from t1bb
where (a1, a2) in (select b1, b2 from t2bb);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1bb ALL NULL NULL NULL NULL 3 100.00 Start temporary
1 PRIMARY t2bb ALL NULL NULL NULL NULL 3 100.00 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t1bb ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY t2bb ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select conv(`test`.`t1bb`.`a1`,10,2) AS `bin(a1)`,`test`.`t1bb`.`a2` AS `a2` from `test`.`t1bb` semi join (`test`.`t2bb`) where ((`test`.`t2bb`.`b2` = `test`.`t1bb`.`a2`) and (`test`.`t2bb`.`b1` = `test`.`t1bb`.`a1`))
select bin(a1), a2
......@@ -1274,8 +1270,8 @@ GROUP BY t3i
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1
1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 5 const 1 Start temporary
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 5 const 1
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
3 SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using temporary
DROP TABLE t1,t2,t3,t4;
......
......@@ -7,7 +7,7 @@ set @subselect_sj2_tmp= @@optimizer_switch;
set optimizer_switch='semijoin=on,firstmatch=on,loosescan=on';
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
--disable_warnings
drop table if exists t0, t1, t2, t3;
drop table if exists t0, t1, t2, t3, t4, t5;
drop view if exists v1;
--enable_warnings
......
#
# Semi-join tests that require Aria
#
--disable_warnings
drop table if exists t1,t2,t3,t4;
--enable_warnings
--echo #
--echo # BUG#887468: Second assertion `keypart_map' failed in maria_rkey with semijoin
--echo #
CREATE TABLE t1 (
pk int(11) NOT NULL AUTO_INCREMENT,
col_int_key int(11) DEFAULT NULL,
col_varchar_key varchar(1) DEFAULT NULL,
dummy char(30),
PRIMARY KEY (pk),
KEY col_varchar_key (col_varchar_key,col_int_key)
) ENGINE=Aria AUTO_INCREMENT=30 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO t1 (pk, col_varchar_key, col_int_key) VALUES
(10,NULL,0), (11,'d',4), (12,'g',8), (13,'x',NULL), (14,'f',NULL),
(15,'p',0), (16,'j',NULL), (17,'c',8), (18,'z',8), (19,'j',6), (20,NULL,2),
(21,'p',3), (22,'w',1), (23,'c',NULL), (24,'j',1), (25,'f',10), (26,'v',2),
(27,'f',103), (28,'q',3), (29,'y',6);
CREATE TABLE t2 (
pk int(11) NOT NULL AUTO_INCREMENT,
col_int_key int(11) DEFAULT NULL,
dummy char(36),
PRIMARY KEY (pk),
KEY col_int_key (col_int_key)
) ENGINE=Aria AUTO_INCREMENT=101 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO t2 ( pk, col_int_key) VALUES
(1,8), (2,2), (3,9), (4,6), (5,NULL), (6,NULL), (7,48), (8,228), (9,3), (10,5),
(11,39), (12,6), (13,8), (14,3), (15,NULL), (16,2), (17,6), (18,3), (19,1), (20,4),
(21,3), (22,1), (23,NULL), (24,97), (25,0), (26,0), (27,9), (28,5), (29,9), (30,0),
(31,2), (32,172), (33,NULL), (34,5), (35,119), (36,1), (37,4), (38,8), (39,NULL), (40,6),
(41,5), (42,5), (43,1), (44,7), (45,2), (46,8), (47,9), (48,NULL), (49,NULL), (50,3),
(51,172), (52,NULL), (53,6), (54,6), (55,5), (56,4), (57,3), (58,2), (59,7), (60,4),
(61,6), (62,0), (63,8), (64,5), (65,8), (66,2), (67,9), (68,7), (69,5), (70,7),
(71,0), (72,4), (73,3), (74,1), (75,0), (76,6), (77,2), (78,NULL), (79,8), (80,NULL),
(81,NULL), (82,NULL), (83,3), (84,7), (85,3), (86,5), (87,5), (88,1), (89,2), (90,1),
(91,7), (92,1), (93,9), (94,9), (95,8), (96,3), (97,7), (98,4), (99,9), (100,0);
CREATE TABLE t3 (
pk int(11) NOT NULL AUTO_INCREMENT,
dummy char(34),
col_varchar_key varchar(1) DEFAULT NULL,
col_int_key int(11) DEFAULT NULL,
PRIMARY KEY (pk),
KEY col_varchar_key (col_varchar_key,col_int_key)
) ENGINE=Aria AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO t3 (pk, col_varchar_key) VALUES (1,'v'), (2,'c'), (3,NULL);
CREATE TABLE t4 (
pk int(11) NOT NULL AUTO_INCREMENT,
dummy char (38),
PRIMARY KEY (pk)
) ENGINE=Aria AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO t4 (pk) VALUES (1), (2), (3);
SELECT *
FROM t1
JOIN t2
ON ( t2.col_int_key = t1.pk )
WHERE t1.col_varchar_key IN (
SELECT t3.col_varchar_key FROM t3, t4
);
drop table t1, t2, t3, t4;
......@@ -2166,227 +2166,180 @@ bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables)
join prefixes each strategy can handle.
*/
void advance_sj_state(JOIN *join, table_map remaining_tables,
const JOIN_TAB *new_join_tab, uint idx,
double *current_record_count, double *current_read_time,
bool is_multiple_semi_joins(JOIN *join, POSITION *prefix, uint idx, table_map inner_tables)
{
for (int i= (int)idx; i >= 0; i--)
{
TABLE_LIST *emb_sj_nest;
if ((emb_sj_nest= prefix[i].table->emb_sj_nest))
{
if (inner_tables & emb_sj_nest->sj_inner_tables)
return !test(inner_tables == (emb_sj_nest->sj_inner_tables &
~join->const_table_map));
}
}
return FALSE;
}
void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
double *current_record_count, double *current_read_time,
POSITION *loose_scan_pos)
{
TABLE_LIST *emb_sj_nest;
POSITION *pos= join->positions + idx;
remaining_tables &= ~new_join_tab->table->map;
bool disable_jbuf= join->thd->variables.join_cache_level == 0;
pos->prefix_cost.convert_from_cost(*current_read_time);
pos->prefix_record_count= *current_record_count;
pos->sj_strategy= SJ_OPT_NONE;
pos->prefix_dups_producing_tables= join->cur_dups_producing_tables;
const JOIN_TAB *new_join_tab= pos->table;
Semi_join_strategy_picker *pickers[]=
{
&pos->firstmatch_picker,
&pos->loosescan_picker,
&pos->sjmat_picker,
&pos->dups_weedout_picker,
NULL,
};
/* We're performing optimization inside SJ-Materialization nest */
if (join->emb_sjm_nest)
{
pos->invalidate_firstmatch_prefix();
pos->first_loosescan_table= MAX_TABLES;
pos->dupsweedout_tables= 0;
pos->sjm_scan_need_tables= 0;
/*
We're performing optimization inside SJ-Materialization nest:
- there are no other semi-joins inside semi-join nests
- attempts to build semi-join strategies here will confuse
the optimizer, so bail out.
*/
pos->sj_strategy= SJ_OPT_NONE;
return;
}
/* Initialize the state or copy it from prev. tables */
if (idx == join->const_tables)
/*
Update join->cur_sj_inner_tables (Used by FirstMatch in this function and
LooseScan detector in best_access_path)
*/
remaining_tables &= ~new_join_tab->table->map;
pos->prefix_dups_producing_tables= join->cur_dups_producing_tables;
TABLE_LIST *emb_sj_nest;
if ((emb_sj_nest= new_join_tab->emb_sj_nest))
{
pos->invalidate_firstmatch_prefix();
pos->first_loosescan_table= MAX_TABLES;
pos->dupsweedout_tables= 0;
pos->sjm_scan_need_tables= 0;
LINT_INIT(pos->sjm_scan_last_inner);
/// join->cur_sj_inner_tables |= emb_sj_nest->sj_inner_tables;
join->cur_dups_producing_tables |= emb_sj_nest->sj_inner_tables;
/* Remove the sj_nest if all of its SJ-inner tables are in cur_table_map */
/// if (!(remaining_tables &
/// emb_sj_nest->sj_inner_tables & ~new_join_tab->table->map))
/// join->cur_sj_inner_tables &= ~emb_sj_nest->sj_inner_tables;
}
else
Semi_join_strategy_picker **strategy;
if (idx == join->const_tables)
{
// FirstMatch
pos->first_firstmatch_table=
(pos[-1].sj_strategy == SJ_OPT_FIRST_MATCH) ?
MAX_TABLES : pos[-1].first_firstmatch_table;
pos->first_firstmatch_rtbl= pos[-1].first_firstmatch_rtbl;
pos->firstmatch_need_tables= pos[-1].firstmatch_need_tables;
// LooseScan
pos->first_loosescan_table=
(pos[-1].sj_strategy == SJ_OPT_LOOSE_SCAN) ?
MAX_TABLES : pos[-1].first_loosescan_table;
pos->loosescan_need_tables= pos[-1].loosescan_need_tables;
// SJ-Materialization Scan
pos->sjm_scan_need_tables=
(pos[-1].sj_strategy == SJ_OPT_MATERIALIZE_SCAN) ?
0 : pos[-1].sjm_scan_need_tables;
pos->sjm_scan_last_inner= pos[-1].sjm_scan_last_inner;
// Duplicate Weedout
pos->dupsweedout_tables= pos[-1].dupsweedout_tables;
pos->first_dupsweedout_table= pos[-1].first_dupsweedout_table;
/* First table, initialize pickers */
for (strategy= pickers; *strategy != NULL; strategy++)
(*strategy)->set_empty();
pos->inner_tables_handled_with_other_sjs= 0;
}
table_map handled_by_fm_or_ls= 0;
/* FirstMatch Strategy */
if (new_join_tab->emb_sj_nest &&
optimizer_flag(join->thd, OPTIMIZER_SWITCH_FIRSTMATCH) &&
!join->outer_join)
else
{
const table_map outer_corr_tables=
new_join_tab->emb_sj_nest->nested_join->sj_corr_tables |
new_join_tab->emb_sj_nest->nested_join->sj_depends_on;
const table_map sj_inner_tables=
new_join_tab->emb_sj_nest->sj_inner_tables & ~join->const_table_map;
/*
Enter condition:
1. The next join tab belongs to semi-join nest
(verified for the encompassing code block above).
2. We're not in a duplicate producer range yet
3. All outer tables that
- the subquery is correlated with, or
- referred to from the outer_expr
are in the join prefix
4. All inner tables are still part of remaining_tables.
*/
if (!join->cur_sj_inner_tables && // (2)
!(remaining_tables & outer_corr_tables) && // (3)
(sj_inner_tables == // (4)
((remaining_tables | new_join_tab->table->map) & sj_inner_tables)))
for (strategy= pickers; *strategy != NULL; strategy++)
{
/* Start tracking potential FirstMatch range */
pos->first_firstmatch_table= idx;
pos->firstmatch_need_tables= sj_inner_tables;
pos->first_firstmatch_rtbl= remaining_tables;
(*strategy)->set_from_prev(pos - 1);
}
pos->inner_tables_handled_with_other_sjs=
pos[-1].inner_tables_handled_with_other_sjs;
}
pos->prefix_cost.convert_from_cost(*current_read_time);
pos->prefix_record_count= *current_record_count;
{
pos->sj_strategy= SJ_OPT_NONE;
if (pos->in_firstmatch_prefix())
for (strategy= pickers; *strategy != NULL; strategy++)
{
if (outer_corr_tables & pos->first_firstmatch_rtbl)
table_map handled_fanout;
sj_strategy_enum sj_strategy;
double rec_count= *current_record_count;
double read_time= *current_read_time;
if ((*strategy)->check_qep(join, idx, remaining_tables,
new_join_tab,
&rec_count,
&read_time,
&handled_fanout,
&sj_strategy,
loose_scan_pos))
{
/*
Trying to add an sj-inner table whose sj-nest has an outer correlated
table that was not in the prefix. This means FirstMatch can't be used.
It's possible to use the strategy. Use it, if
- it removes semi-join fanout that was not removed before
- using it is cheaper than using something else,
and {if some other strategy has removed fanout
that this strategy is trying to remove, then it
did remove the fanout only for one semi-join}
This is to avoid a situation when
1. strategy X removes fanout for semijoin X,Y
2. using strategy Z is cheaper, but it only removes
fanout from semijoin X.
3. We have no clue what to do about fanount of semi-join Y.
*/
pos->invalidate_firstmatch_prefix();
}
else
{
/* Record that we need all of this semi-join's inner tables, too */
pos->firstmatch_need_tables|= sj_inner_tables;
}
if (pos->in_firstmatch_prefix() &&
!(pos->firstmatch_need_tables & remaining_tables))
{
/*
Got a complete FirstMatch range.
Calculate correct costs and fanout
*/
optimize_wo_join_buffering(join, pos->first_firstmatch_table, idx,
remaining_tables, FALSE, idx,
current_record_count,
current_read_time);
/*
We don't yet know what are the other strategies, so pick the
FirstMatch.
We ought to save the alternate POSITIONs produced by
optimize_wo_join_buffering but the problem is that providing save
space uses too much space. Instead, we will re-calculate the
alternate POSITIONs after we've picked the best QEP.
*/
pos->sj_strategy= SJ_OPT_FIRST_MATCH;
handled_by_fm_or_ls= pos->firstmatch_need_tables;
if ((join->cur_dups_producing_tables & handled_fanout) ||
(read_time < *current_read_time &&
!(handled_fanout & pos->inner_tables_handled_with_other_sjs)))
{
/* Mark strategy as used */
(*strategy)->mark_used();
pos->sj_strategy= sj_strategy;
*current_read_time= read_time;
*current_record_count= rec_count;
join->cur_dups_producing_tables &= ~handled_fanout;
//TODO: update bitmap of semi-joins that were handled together with
// others.
if (is_multiple_semi_joins(join, join->positions, idx, handled_fanout))
pos->inner_tables_handled_with_other_sjs |= handled_fanout;
}
else
{
/* We decided not to apply the strategy. */
(*strategy)->set_empty();
}
}
}
}
/* LooseScan Strategy */
{
POSITION *first=join->positions+pos->first_loosescan_table;
/*
LooseScan strategy can't handle interleaving between tables from the
semi-join that LooseScan is handling and any other tables.
If we were considering LooseScan for the join prefix (1)
and the table we're adding creates an interleaving (2)
then
stop considering loose scan
*/
if ((pos->first_loosescan_table != MAX_TABLES) && // (1)
(first->table->emb_sj_nest->sj_inner_tables & remaining_tables) && //(2)
new_join_tab->emb_sj_nest != first->table->emb_sj_nest) //(2)
{
pos->first_loosescan_table= MAX_TABLES;
}
/*
If we got an option to use LooseScan for the current table, start
considering using LooseScan strategy
*/
if (loose_scan_pos->read_time != DBL_MAX && !join->outer_join)
{
pos->first_loosescan_table= idx;
pos->loosescan_need_tables=
new_join_tab->emb_sj_nest->sj_inner_tables |
new_join_tab->emb_sj_nest->nested_join->sj_depends_on |
new_join_tab->emb_sj_nest->nested_join->sj_corr_tables;
}
if ((pos->first_loosescan_table != MAX_TABLES) &&
!(remaining_tables & pos->loosescan_need_tables))
{
/*
Ok we have LooseScan plan and also have all LooseScan sj-nest's
inner tables and outer correlated tables into the prefix.
*/
first=join->positions + pos->first_loosescan_table;
uint n_tables= my_count_bits(first->table->emb_sj_nest->sj_inner_tables);
/* Got a complete LooseScan range. Calculate its cost */
/*
The same problem as with FirstMatch - we need to save POSITIONs
somewhere but reserving space for all cases would require too
much space. We will re-calculate POSITION structures later on.
*/
optimize_wo_join_buffering(join, pos->first_loosescan_table, idx,
remaining_tables,
TRUE, //first_alt
disable_jbuf ? join->table_count :
pos->first_loosescan_table + n_tables,
current_record_count,
current_read_time);
/*
We don't yet have any other strategies that could handle this
semi-join nest (the other options are Duplicate Elimination or
Materialization, which need at least the same set of tables in
the join prefix to be considered) so unconditionally pick the
LooseScan.
*/
pos->sj_strategy= SJ_OPT_LOOSE_SCAN;
handled_by_fm_or_ls= first->table->emb_sj_nest->sj_inner_tables;
}
}
/*
Update join->cur_sj_inner_tables (Used by FirstMatch in this function and
LooseScan detector in best_access_path)
*/
if ((emb_sj_nest= new_join_tab->emb_sj_nest))
{
join->cur_sj_inner_tables |= emb_sj_nest->sj_inner_tables;
join->cur_dups_producing_tables |= emb_sj_nest->sj_inner_tables;
/* Remove the sj_nest if all of its SJ-inner tables are in cur_table_map */
if (!(remaining_tables &
emb_sj_nest->sj_inner_tables & ~new_join_tab->table->map))
join->cur_sj_inner_tables &= ~emb_sj_nest->sj_inner_tables;
}
join->cur_dups_producing_tables &= ~handled_by_fm_or_ls;
/* 4. SJ-Materialization and SJ-Materialization-scan strategy handler */
pos->prefix_cost.convert_from_cost(*current_read_time);
pos->prefix_record_count= *current_record_count;
}
void Sj_materialization_picker::set_from_prev(struct st_position *prev)
{
if (prev->sjmat_picker.is_used)
set_empty();
else
{
sjm_scan_need_tables= prev->sjmat_picker.sjm_scan_need_tables;
sjm_scan_last_inner= prev->sjmat_picker.sjm_scan_last_inner;
}
is_used= FALSE;
}
bool Sj_materialization_picker::check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
const JOIN_TAB *new_join_tab,
double *record_count,
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
POSITION *loose_scan_pos)
{
bool sjm_scan;
SJ_MATERIALIZATION_INFO *mat_info;
if ((mat_info= at_sjmat_pos(join, remaining_tables,
......@@ -2413,11 +2366,11 @@ void advance_sj_state(JOIN *join, table_map remaining_tables,
The simple way to model this is to remove SJM-SCAN(...) fanout once
we reach the point #2.
*/
pos->sjm_scan_need_tables=
sjm_scan_need_tables=
new_join_tab->emb_sj_nest->sj_inner_tables |
new_join_tab->emb_sj_nest->nested_join->sj_depends_on |
new_join_tab->emb_sj_nest->nested_join->sj_corr_tables;
pos->sjm_scan_last_inner= idx;
sjm_scan_last_inner= idx;
}
else
{
......@@ -2440,34 +2393,31 @@ void advance_sj_state(JOIN *join, table_map remaining_tables,
mat_read_time += mat_info->materialization_cost.total_cost() +
prefix_rec_count * mat_info->lookup_cost.total_cost();
if (mat_read_time < *current_read_time || join->cur_dups_producing_tables)
{
/*
NOTE: When we pick to use SJM[-Scan] we don't memcpy its POSITION
elements to join->positions as that makes it hard to return things
back when making one step back in join optimization. That's done
after the QEP has been chosen.
*/
pos->sj_strategy= SJ_OPT_MATERIALIZE;
*current_read_time= mat_read_time;
*current_record_count= prefix_rec_count;
join->cur_dups_producing_tables&=
~new_join_tab->emb_sj_nest->sj_inner_tables;
}
/*
NOTE: When we pick to use SJM[-Scan] we don't memcpy its POSITION
elements to join->positions as that makes it hard to return things
back when making one step back in join optimization. That's done
after the QEP has been chosen.
*/
*read_time= mat_read_time;
*record_count= prefix_rec_count;
*handled_fanout= new_join_tab->emb_sj_nest->sj_inner_tables;
*strategy= SJ_OPT_MATERIALIZE;
return TRUE;
}
}
/* 4.A SJM-Scan second phase check */
if (pos->sjm_scan_need_tables && /* Have SJM-Scan prefix */
!(pos->sjm_scan_need_tables & remaining_tables))
if (sjm_scan_need_tables && /* Have SJM-Scan prefix */
!(sjm_scan_need_tables & remaining_tables))
{
TABLE_LIST *mat_nest=
join->positions[pos->sjm_scan_last_inner].table->emb_sj_nest;
join->positions[sjm_scan_last_inner].table->emb_sj_nest;
SJ_MATERIALIZATION_INFO *mat_info= mat_nest->sj_mat_info;
double prefix_cost;
double prefix_rec_count;
int first_tab= pos->sjm_scan_last_inner + 1 - mat_info->tables;
int first_tab= sjm_scan_last_inner + 1 - mat_info->tables;
/* Get the prefix cost */
if (first_tab == (int)join->const_tables)
{
......@@ -2492,6 +2442,7 @@ void advance_sj_state(JOIN *join, table_map remaining_tables,
POSITION curpos, dummy;
/* Need to re-run best-access-path as we prefix_rec_count has changed */
bool disable_jbuf= (join->thd->variables.join_cache_level == 0);
for (i= first_tab + mat_info->tables; i <= idx; i++)
{
best_access_path(join, join->positions[i].table, rem_tables, i,
......@@ -2500,142 +2451,333 @@ void advance_sj_state(JOIN *join, table_map remaining_tables,
prefix_cost += curpos.read_time;
}
*strategy= SJ_OPT_MATERIALIZE_SCAN;
*read_time= prefix_cost;
*record_count= prefix_rec_count;
*handled_fanout= mat_nest->sj_inner_tables;
return TRUE;
}
return FALSE;
}
void LooseScan_picker::set_from_prev(struct st_position *prev)
{
if (prev->loosescan_picker.is_used)
set_empty();
else
{
first_loosescan_table= prev->loosescan_picker.first_loosescan_table;
loosescan_need_tables= prev->loosescan_picker.loosescan_need_tables;
}
is_used= FALSE;
}
bool LooseScan_picker::check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
const JOIN_TAB *new_join_tab,
double *record_count,
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
struct st_position *loose_scan_pos)
{
POSITION *first= join->positions + first_loosescan_table;
/*
LooseScan strategy can't handle interleaving between tables from the
semi-join that LooseScan is handling and any other tables.
If we were considering LooseScan for the join prefix (1)
and the table we're adding creates an interleaving (2)
then
stop considering loose scan
*/
if ((first_loosescan_table != MAX_TABLES) && // (1)
(first->table->emb_sj_nest->sj_inner_tables & remaining_tables) && //(2)
new_join_tab->emb_sj_nest != first->table->emb_sj_nest) //(2)
{
first_loosescan_table= MAX_TABLES;
}
/*
If we got an option to use LooseScan for the current table, start
considering using LooseScan strategy
*/
if (loose_scan_pos->read_time != DBL_MAX && !join->outer_join)
{
first_loosescan_table= idx;
loosescan_need_tables=
new_join_tab->emb_sj_nest->sj_inner_tables |
new_join_tab->emb_sj_nest->nested_join->sj_depends_on |
new_join_tab->emb_sj_nest->nested_join->sj_corr_tables;
}
if ((first_loosescan_table != MAX_TABLES) &&
!(remaining_tables & loosescan_need_tables) &&
(new_join_tab->table->map & loosescan_need_tables))
{
/*
Ok we have LooseScan plan and also have all LooseScan sj-nest's
inner tables and outer correlated tables into the prefix.
*/
first= join->positions + first_loosescan_table;
uint n_tables= my_count_bits(first->table->emb_sj_nest->sj_inner_tables);
/* Got a complete LooseScan range. Calculate its cost */
/*
Use the strategy if
* it is cheaper then what we've had, or
* we haven't picked any other semi-join strategy yet
In the second case, we pick this strategy unconditionally because
comparing cost without semi-join duplicate removal with cost with
duplicate removal is not an apples-to-apples comparison.
The same problem as with FirstMatch - we need to save POSITIONs
somewhere but reserving space for all cases would require too
much space. We will re-calculate POSITION structures later on.
*/
if (prefix_cost < *current_read_time || join->cur_dups_producing_tables)
{
pos->sj_strategy= SJ_OPT_MATERIALIZE_SCAN;
*current_read_time= prefix_cost;
*current_record_count= prefix_rec_count;
join->cur_dups_producing_tables&= ~mat_nest->sj_inner_tables;
bool disable_jbuf= (join->thd->variables.join_cache_level == 0);
optimize_wo_join_buffering(join, first_loosescan_table, idx,
remaining_tables,
TRUE, //first_alt
disable_jbuf ? join->table_count :
first_loosescan_table + n_tables,
record_count,
read_time);
/*
We don't yet have any other strategies that could handle this
semi-join nest (the other options are Duplicate Elimination or
Materialization, which need at least the same set of tables in
the join prefix to be considered) so unconditionally pick the
LooseScan.
*/
*strategy= SJ_OPT_LOOSE_SCAN;
*handled_fanout= first->table->emb_sj_nest->sj_inner_tables;
return TRUE;
}
return FALSE;
}
}
void Firstmatch_picker::set_from_prev(struct st_position *prev)
{
if (prev->firstmatch_picker.is_used)
invalidate_firstmatch_prefix();
else
{
first_firstmatch_table= prev->firstmatch_picker.first_firstmatch_table;
first_firstmatch_rtbl= prev->firstmatch_picker.first_firstmatch_rtbl;
firstmatch_need_tables= prev->firstmatch_picker.firstmatch_need_tables;
}
is_used= FALSE;
}
/* 5. Duplicate Weedout strategy handler */
bool Firstmatch_picker::check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
const JOIN_TAB *new_join_tab,
double *record_count,
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
POSITION *loose_scan_pos)
{
if (new_join_tab->emb_sj_nest &&
optimizer_flag(join->thd, OPTIMIZER_SWITCH_FIRSTMATCH) &&
!join->outer_join)
{
const table_map outer_corr_tables=
new_join_tab->emb_sj_nest->nested_join->sj_corr_tables |
new_join_tab->emb_sj_nest->nested_join->sj_depends_on;
const table_map sj_inner_tables=
new_join_tab->emb_sj_nest->sj_inner_tables & ~join->const_table_map;
/*
Duplicate weedout can be applied after all ON-correlated and
correlated
Enter condition:
1. The next join tab belongs to semi-join nest
(verified for the encompassing code block above).
2. We're not in a duplicate producer range yet
3. All outer tables that
- the subquery is correlated with, or
- referred to from the outer_expr
are in the join prefix
4. All inner tables are still part of remaining_tables.
*/
TABLE_LIST *nest;
if ((nest= new_join_tab->emb_sj_nest))
{
if (!pos->dupsweedout_tables)
pos->first_dupsweedout_table= idx;
pos->dupsweedout_tables |= nest->sj_inner_tables |
nest->nested_join->sj_depends_on |
nest->nested_join->sj_corr_tables;
}
if (pos->dupsweedout_tables)
if (!join->cur_sj_inner_tables && // (2)
!(remaining_tables & outer_corr_tables) && // (3)
(sj_inner_tables == // (4)
((remaining_tables | new_join_tab->table->map) & sj_inner_tables)))
{
/* we're in the process of constructing a DuplicateWeedout range */
TABLE_LIST *emb= new_join_tab->table->pos_in_table_list->embedding;
/* and we've entered an inner side of an outer join*/
if (emb && emb->on_expr)
pos->dupsweedout_tables |= emb->nested_join->used_tables;
/* Start tracking potential FirstMatch range */
first_firstmatch_table= idx;
firstmatch_need_tables= sj_inner_tables;
first_firstmatch_rtbl= remaining_tables;
}
if (pos->dupsweedout_tables &&
!(remaining_tables &
~new_join_tab->table->map & pos->dupsweedout_tables))
if (in_firstmatch_prefix())
{
/*
Ok, reached a state where we could put a dups weedout point.
Walk back and calculate
- the join cost (this is needed as the accumulated cost may assume
some other duplicate elimination method)
- extra fanout that will be removed by duplicate elimination
- duplicate elimination cost
There are two cases:
1. We have other strategy/ies to remove all of the duplicates.
2. We don't.
We need to calculate the cost in case #2 also because we need to make
choice between this join order and others.
*/
uint first_tab= pos->first_dupsweedout_table;
double dups_cost;
double prefix_rec_count;
double sj_inner_fanout= 1.0;
double sj_outer_fanout= 1.0;
uint temptable_rec_size;
if (first_tab == join->const_tables)
if (outer_corr_tables & first_firstmatch_rtbl)
{
prefix_rec_count= 1.0;
temptable_rec_size= 0;
dups_cost= 0.0;
/*
Trying to add an sj-inner table whose sj-nest has an outer correlated
table that was not in the prefix. This means FirstMatch can't be used.
*/
invalidate_firstmatch_prefix();
}
else
{
dups_cost= join->positions[first_tab - 1].prefix_cost.total_cost();
prefix_rec_count= join->positions[first_tab - 1].prefix_record_count;
temptable_rec_size= 8; /* This is not true but we'll make it so */
/* Record that we need all of this semi-join's inner tables, too */
firstmatch_need_tables|= sj_inner_tables;
}
table_map dups_removed_fanout= 0;
for (uint j= pos->first_dupsweedout_table; j <= idx; j++)
if (in_firstmatch_prefix() &&
!(firstmatch_need_tables & remaining_tables))
{
POSITION *p= join->positions + j;
dups_cost += p->read_time;
if (p->table->emb_sj_nest)
{
sj_inner_fanout *= p->records_read;
dups_removed_fanout |= p->table->table->map;
}
else
{
sj_outer_fanout *= p->records_read;
temptable_rec_size += p->table->table->file->ref_length;
}
/*
Got a complete FirstMatch range.
Calculate correct costs and fanout
*/
optimize_wo_join_buffering(join, first_firstmatch_table, idx,
remaining_tables, FALSE, idx,
record_count,
read_time);
/*
We ought to save the alternate POSITIONs produced by
optimize_wo_join_buffering but the problem is that providing save
space uses too much space. Instead, we will re-calculate the
alternate POSITIONs after we've picked the best QEP.
*/
*handled_fanout= firstmatch_need_tables;
/* *record_count and *read_time were set by the above call */
*strategy= SJ_OPT_FIRST_MATCH;
return TRUE;
}
}
}
return FALSE;
}
/*
Add the cost of temptable use. The table will have sj_outer_fanout
records, and we will make
- sj_outer_fanout table writes
- sj_inner_fanout*sj_outer_fanout lookups.
*/
double one_lookup_cost= get_tmp_table_lookup_cost(join->thd,
sj_outer_fanout,
temptable_rec_size);
double one_write_cost= get_tmp_table_write_cost(join->thd,
sj_outer_fanout,
temptable_rec_size);
void Duplicate_weedout_picker::set_from_prev(POSITION *prev)
{
if (prev->dups_weedout_picker.is_used)
set_empty();
else
{
dupsweedout_tables= prev->dups_weedout_picker.dupsweedout_tables;
first_dupsweedout_table= prev->dups_weedout_picker.first_dupsweedout_table;
}
is_used= FALSE;
}
double write_cost= join->positions[first_tab].prefix_record_count*
sj_outer_fanout * one_write_cost;
double full_lookup_cost= join->positions[first_tab].prefix_record_count*
sj_outer_fanout* sj_inner_fanout *
one_lookup_cost;
dups_cost += write_cost + full_lookup_cost;
bool Duplicate_weedout_picker::check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
const JOIN_TAB *new_join_tab,
double *record_count,
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
POSITION *loose_scan_pos
)
{
TABLE_LIST *nest;
if ((nest= new_join_tab->emb_sj_nest))
{
if (!dupsweedout_tables)
first_dupsweedout_table= idx;
dupsweedout_tables |= nest->sj_inner_tables |
nest->nested_join->sj_depends_on |
nest->nested_join->sj_corr_tables;
}
if (dupsweedout_tables)
{
/* we're in the process of constructing a DuplicateWeedout range */
TABLE_LIST *emb= new_join_tab->table->pos_in_table_list->embedding;
/* and we've entered an inner side of an outer join*/
if (emb && emb->on_expr)
dupsweedout_tables |= emb->nested_join->used_tables;
}
/* If this is the last table that we need for DuplicateWeedout range */
if (dupsweedout_tables && !(remaining_tables & ~new_join_tab->table->map &
dupsweedout_tables))
{
/*
Ok, reached a state where we could put a dups weedout point.
Walk back and calculate
- the join cost (this is needed as the accumulated cost may assume
some other duplicate elimination method)
- extra fanout that will be removed by duplicate elimination
- duplicate elimination cost
There are two cases:
1. We have other strategy/ies to remove all of the duplicates.
2. We don't.
/*
Use the strategy if
* it is cheaper then what we've had, or
* we haven't picked any other semi-join strategy yet
The second part is necessary because this strategy is the last one
to consider (it needs "the most" tables in the prefix) and we can't
leave duplicate-producing tables not handled by any strategy.
*/
if (dups_cost < *current_read_time || join->cur_dups_producing_tables)
We need to calculate the cost in case #2 also because we need to make
choice between this join order and others.
*/
uint first_tab= first_dupsweedout_table;
double dups_cost;
double prefix_rec_count;
double sj_inner_fanout= 1.0;
double sj_outer_fanout= 1.0;
uint temptable_rec_size;
if (first_tab == join->const_tables)
{
prefix_rec_count= 1.0;
temptable_rec_size= 0;
dups_cost= 0.0;
}
else
{
dups_cost= join->positions[first_tab - 1].prefix_cost.total_cost();
prefix_rec_count= join->positions[first_tab - 1].prefix_record_count;
temptable_rec_size= 8; /* This is not true but we'll make it so */
}
table_map dups_removed_fanout= 0;
for (uint j= first_dupsweedout_table; j <= idx; j++)
{
POSITION *p= join->positions + j;
dups_cost += p->read_time;
if (p->table->emb_sj_nest)
{
pos->sj_strategy= SJ_OPT_DUPS_WEEDOUT;
*current_read_time= dups_cost;
*current_record_count= prefix_rec_count * sj_outer_fanout;
join->cur_dups_producing_tables &= ~dups_removed_fanout;
sj_inner_fanout *= p->records_read;
dups_removed_fanout |= p->table->table->map;
}
else
{
sj_outer_fanout *= p->records_read;
temptable_rec_size += p->table->table->file->ref_length;
}
}
/*
Add the cost of temptable use. The table will have sj_outer_fanout
records, and we will make
- sj_outer_fanout table writes
- sj_inner_fanout*sj_outer_fanout lookups.
*/
double one_lookup_cost= get_tmp_table_lookup_cost(join->thd,
sj_outer_fanout,
temptable_rec_size);
double one_write_cost= get_tmp_table_write_cost(join->thd,
sj_outer_fanout,
temptable_rec_size);
double write_cost= join->positions[first_tab].prefix_record_count*
sj_outer_fanout * one_write_cost;
double full_lookup_cost= join->positions[first_tab].prefix_record_count*
sj_outer_fanout* sj_inner_fanout *
one_lookup_cost;
dups_cost += write_cost + full_lookup_cost;
*read_time= dups_cost;
*record_count= prefix_rec_count * sj_outer_fanout;
*handled_fanout= dups_removed_fanout;
*strategy= SJ_OPT_DUPS_WEEDOUT;
return TRUE;
}
return FALSE;
}
......@@ -2832,11 +2974,11 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
}
else if (pos->sj_strategy == SJ_OPT_MATERIALIZE_SCAN)
{
POSITION *first_inner= join->best_positions + pos->sjm_scan_last_inner;
POSITION *first_inner= join->best_positions + pos->sjmat_picker.sjm_scan_last_inner;
SJ_MATERIALIZATION_INFO *sjm= first_inner->table->emb_sj_nest->sj_mat_info;
sjm->is_used= TRUE;
sjm->is_sj_scan= TRUE;
first= pos->sjm_scan_last_inner - sjm->tables + 1;
first= pos->sjmat_picker.sjm_scan_last_inner - sjm->tables + 1;
memcpy(join->best_positions + first,
sjm->positions, sizeof(POSITION) * sjm->tables);
join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE_SCAN;
......@@ -2874,7 +3016,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
if (pos->sj_strategy == SJ_OPT_FIRST_MATCH)
{
first= pos->first_firstmatch_table;
first= pos->firstmatch_picker.first_firstmatch_table;
join->best_positions[first].sj_strategy= SJ_OPT_FIRST_MATCH;
join->best_positions[first].n_sj_tables= tablenr - first + 1;
POSITION dummy; // For loose scan paths
......@@ -2907,7 +3049,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
if (pos->sj_strategy == SJ_OPT_LOOSE_SCAN)
{
first= pos->first_loosescan_table;
first= pos->loosescan_picker.first_loosescan_table;
POSITION *first_pos= join->best_positions + first;
POSITION loose_scan_pos; // For loose scan paths
double record_count= (first== join->const_tables)? 1.0:
......@@ -2946,7 +3088,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
Duplicate Weedout starting at pos->first_dupsweedout_table, ending at
this table.
*/
first= pos->first_dupsweedout_table;
first= pos->dups_weedout_picker.first_dupsweedout_table;
join->best_positions[first].sj_strategy= SJ_OPT_DUPS_WEEDOUT;
join->best_positions[first].n_sj_tables= tablenr - first + 1;
}
......@@ -3764,6 +3906,80 @@ int do_sj_dups_weedout(THD *thd, SJ_TMP_TABLE *sjtbl)
}
int init_dups_weedout(JOIN *join, uint first_table, int first_fanout_table, uint n_tables)
{
THD *thd= join->thd;
DBUG_ENTER("init_dups_weedout");
SJ_TMP_TABLE::TAB sjtabs[MAX_TABLES];
SJ_TMP_TABLE::TAB *last_tab= sjtabs;
uint jt_rowid_offset= 0; // # tuple bytes are already occupied (w/o NULL bytes)
uint jt_null_bits= 0; // # null bits in tuple bytes
/*
Walk through the range and remember
- tables that need their rowids to be put into temptable
- the last outer table
*/
for (JOIN_TAB *j=join->join_tab + first_table;
j < join->join_tab + first_table + n_tables; j++)
{
if (sj_table_is_included(join, j))
{
last_tab->join_tab= j;
last_tab->rowid_offset= jt_rowid_offset;
jt_rowid_offset += j->table->file->ref_length;
if (j->table->maybe_null)
{
last_tab->null_byte= jt_null_bits / 8;
last_tab->null_bit= jt_null_bits++;
}
last_tab++;
j->table->prepare_for_position();
j->keep_current_rowid= TRUE;
}
}
SJ_TMP_TABLE *sjtbl;
if (jt_rowid_offset) /* Temptable has at least one rowid */
{
size_t tabs_size= (last_tab - sjtabs) * sizeof(SJ_TMP_TABLE::TAB);
if (!(sjtbl= (SJ_TMP_TABLE*)thd->alloc(sizeof(SJ_TMP_TABLE))) ||
!(sjtbl->tabs= (SJ_TMP_TABLE::TAB*) thd->alloc(tabs_size)))
DBUG_RETURN(TRUE); /* purecov: inspected */
memcpy(sjtbl->tabs, sjtabs, tabs_size);
sjtbl->is_degenerate= FALSE;
sjtbl->tabs_end= sjtbl->tabs + (last_tab - sjtabs);
sjtbl->rowid_len= jt_rowid_offset;
sjtbl->null_bits= jt_null_bits;
sjtbl->null_bytes= (jt_null_bits + 7)/8;
sjtbl->tmp_table=
create_duplicate_weedout_tmp_table(thd,
sjtbl->rowid_len +
sjtbl->null_bytes,
sjtbl);
join->sj_tmp_tables.push_back(sjtbl->tmp_table);
}
else
{
/*
This is a special case where the entire subquery predicate does
not depend on anything at all, ie this is
WHERE const IN (uncorrelated select)
*/
if (!(sjtbl= (SJ_TMP_TABLE*)thd->alloc(sizeof(SJ_TMP_TABLE))))
DBUG_RETURN(TRUE); /* purecov: inspected */
sjtbl->tmp_table= NULL;
sjtbl->is_degenerate= TRUE;
sjtbl->have_degenerate_row= FALSE;
}
sjtbl->next_flush_table= join->join_tab[first_table].flush_weedout_table;
join->join_tab[first_table].flush_weedout_table= sjtbl;
join->join_tab[first_fanout_table].first_weedout_table= sjtbl;
join->join_tab[first_table + n_tables - 1].check_weed_out_table= sjtbl;
DBUG_RETURN(0);
}
/*
Setup the strategies to eliminate semi-join duplicates.
......@@ -3864,9 +4080,9 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
uint no_jbuf_after)
{
uint i;
THD *thd= join->thd;
DBUG_ENTER("setup_semijoin_dups_elimination");
POSITION *pos= join->best_positions + join->const_tables;
for (i= join->const_tables ; i < join->top_join_tab_count; )
{
......@@ -3889,8 +4105,8 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
/* Calculate key length */
keylen= 0;
keyno= pos->loosescan_key;
for (uint kp=0; kp < pos->loosescan_parts; kp++)
keyno= pos->loosescan_picker.loosescan_key;
for (uint kp=0; kp < pos->loosescan_picker.loosescan_parts; kp++)
keylen += tab->table->key_info[keyno].key_part[kp].store_length;
tab->loosescan_key_len= keylen;
......@@ -3907,6 +4123,7 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
forwards, but do not destroy other duplicate elimination methods.
*/
uint first_table= i;
uint join_cache_level= join->thd->variables.join_cache_level;
for (uint j= i; j < i + pos->n_sj_tables; j++)
{
......@@ -3930,70 +4147,7 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
}
}
SJ_TMP_TABLE::TAB sjtabs[MAX_TABLES];
SJ_TMP_TABLE::TAB *last_tab= sjtabs;
uint jt_rowid_offset= 0; // # tuple bytes are already occupied (w/o NULL bytes)
uint jt_null_bits= 0; // # null bits in tuple bytes
/*
Walk through the range and remember
- tables that need their rowids to be put into temptable
- the last outer table
*/
for (JOIN_TAB *j=join->join_tab + first_table;
j < join->join_tab + i + pos->n_sj_tables; j++)
{
if (sj_table_is_included(join, j))
{
last_tab->join_tab= j;
last_tab->rowid_offset= jt_rowid_offset;
jt_rowid_offset += j->table->file->ref_length;
if (j->table->maybe_null)
{
last_tab->null_byte= jt_null_bits / 8;
last_tab->null_bit= jt_null_bits++;
}
last_tab++;
j->table->prepare_for_position();
j->keep_current_rowid= TRUE;
}
}
SJ_TMP_TABLE *sjtbl;
if (jt_rowid_offset) /* Temptable has at least one rowid */
{
size_t tabs_size= (last_tab - sjtabs) * sizeof(SJ_TMP_TABLE::TAB);
if (!(sjtbl= (SJ_TMP_TABLE*)thd->alloc(sizeof(SJ_TMP_TABLE))) ||
!(sjtbl->tabs= (SJ_TMP_TABLE::TAB*) thd->alloc(tabs_size)))
DBUG_RETURN(TRUE); /* purecov: inspected */
memcpy(sjtbl->tabs, sjtabs, tabs_size);
sjtbl->is_degenerate= FALSE;
sjtbl->tabs_end= sjtbl->tabs + (last_tab - sjtabs);
sjtbl->rowid_len= jt_rowid_offset;
sjtbl->null_bits= jt_null_bits;
sjtbl->null_bytes= (jt_null_bits + 7)/8;
sjtbl->tmp_table=
create_duplicate_weedout_tmp_table(thd,
sjtbl->rowid_len +
sjtbl->null_bytes,
sjtbl);
join->sj_tmp_tables.push_back(sjtbl->tmp_table);
}
else
{
/*
This is a special case where the entire subquery predicate does
not depend on anything at all, ie this is
WHERE const IN (uncorrelated select)
*/
if (!(sjtbl= (SJ_TMP_TABLE*)thd->alloc(sizeof(SJ_TMP_TABLE))))
DBUG_RETURN(TRUE); /* purecov: inspected */
sjtbl->tmp_table= NULL;
sjtbl->is_degenerate= TRUE;
sjtbl->have_degenerate_row= FALSE;
}
join->join_tab[first_table].flush_weedout_table= sjtbl;
join->join_tab[i + pos->n_sj_tables - 1].check_weed_out_table= sjtbl;
init_dups_weedout(join, first_table, i, i + pos->n_sj_tables - first_table);
i+= pos->n_sj_tables;
pos+= pos->n_sj_tables;
break;
......
......@@ -263,8 +263,8 @@ class Loose_scan_opt
{
pos->records_read= best_loose_scan_records;
pos->key= best_loose_scan_start_key;
pos->loosescan_key= best_loose_scan_key;
pos->loosescan_parts= best_max_loose_keypart + 1;
pos->loosescan_picker.loosescan_key= best_loose_scan_key;
pos->loosescan_picker.loosescan_parts= best_max_loose_keypart + 1;
pos->use_join_buffer= FALSE;
pos->table= tab;
// todo need ref_depend_map ?
......@@ -277,8 +277,7 @@ class Loose_scan_opt
};
void advance_sj_state(JOIN *join, const table_map remaining_tables,
const JOIN_TAB *new_join_tab, uint idx,
void advance_sj_state(JOIN *join, const table_map remaining_tables, uint idx,
double *current_record_count, double *current_read_time,
POSITION *loose_scan_pos);
void restore_prev_sj_state(const table_map remaining_tables,
......@@ -359,8 +358,7 @@ class SJ_TMP_TABLE : public Sql_alloc
ENGINE_COLUMNDEF *start_recinfo;
ENGINE_COLUMNDEF *recinfo;
/* Pointer to next table (next->start_idx > this->end_idx) */
SJ_TMP_TABLE *next;
SJ_TMP_TABLE *next_flush_table;
};
int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
......
......@@ -85,7 +85,7 @@ static int join_tab_cmp_embedded_first(const void *emb, const void* ptr1, const
static bool find_best(JOIN *join,table_map rest_tables,uint index,
double record_count,double read_time);
static uint cache_record_length(JOIN *join,uint index);
static bool get_best_combination(JOIN *join);
bool get_best_combination(JOIN *join);
static store_key *get_store_key(THD *thd,
KEYUSE *keyuse, table_map used_tables,
KEY_PART_INFO *key_part, uchar *key_buff,
......@@ -4887,7 +4887,7 @@ void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
join->positions[idx].records_read=1.0; /* This is a const table */
join->positions[idx].ref_depend_map= 0;
join->positions[idx].loosescan_key= MAX_KEY; /* Not a LooseScan */
// join->positions[idx].loosescan_key= MAX_KEY; /* Not a LooseScan */
join->positions[idx].sj_strategy= SJ_OPT_NONE;
join->positions[idx].use_join_buffer= FALSE;
......@@ -5537,7 +5537,7 @@ best_access_path(JOIN *join,
pos->key= best_key;
pos->table= s;
pos->ref_depend_map= best_ref_depends_map;
pos->loosescan_key= MAX_KEY;
pos->loosescan_picker.loosescan_key= MAX_KEY;
pos->use_join_buffer= best_uses_jbuf;
loose_scan_opt.save_to_position(s, loose_scan_pos);
......@@ -5844,7 +5844,7 @@ optimize_straight_join(JOIN *join, table_map join_tables)
/* compute the cost of the new plan extended with 's' */
record_count*= join->positions[idx].records_read;
read_time+= join->positions[idx].read_time;
advance_sj_state(join, join_tables, s, idx, &record_count, &read_time,
advance_sj_state(join, join_tables, idx, &record_count, &read_time,
&loose_scan_pos);
join_tables&= ~(s->table->map);
......@@ -6360,7 +6360,7 @@ best_extension_by_limited_search(JOIN *join,
current_record_count= record_count * position->records_read;
current_read_time= read_time + position->read_time;
advance_sj_state(join, remaining_tables, s, idx, &current_record_count,
advance_sj_state(join, remaining_tables, idx, &current_record_count,
&current_read_time, &loose_scan_pos);
/* Expand only partial plans with lower cost than the best QEP so far */
......@@ -6517,7 +6517,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
*/
double current_record_count=record_count*records;
double current_read_time=read_time+best;
advance_sj_state(join, rest_tables, s, idx, &current_record_count,
advance_sj_state(join, rest_tables, idx, &current_record_count,
&current_read_time, &loose_scan_pos);
if (best_record_count > current_record_count ||
......@@ -7017,7 +7017,7 @@ static Item * const null_ptr= NULL;
TRUE Out of memory
*/
static bool
bool
get_best_combination(JOIN *join)
{
uint tablenr;
......@@ -7095,13 +7095,6 @@ get_best_combination(JOIN *join)
*j= *join->best_positions[tablenr].table;
#if 0
/* SJ-Materialization is represented with join tab ranges */
if (j->sj_strategy == SJ_OPT_MATERIALIZE ||
j->sj_strategy == SJ_OPT_MATERIALIZE)
j->sj_strategy= SJ_OPT_NONE;
#endif
j->bush_root_tab= sjm_nest_root;
form=join->table[tablenr]=j->table;
......@@ -7124,7 +7117,7 @@ get_best_combination(JOIN *join)
(join->best_positions[tablenr].sj_strategy == SJ_OPT_LOOSE_SCAN))
{
j->type=JT_ALL;
j->index= join->best_positions[tablenr].loosescan_key;
j->index= join->best_positions[tablenr].loosescan_picker.loosescan_key;
if (tablenr != join->const_tables)
join->full_join=1;
}
......@@ -15107,10 +15100,12 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
int error;
enum_nested_loop_state rc= NESTED_LOOP_OK;
READ_RECORD *info= &join_tab->read_record;
if (join_tab->flush_weedout_table)
for (SJ_TMP_TABLE *flush_dups_table= join_tab->flush_weedout_table;
flush_dups_table;
flush_dups_table= flush_dups_table->next_flush_table)
{
do_sj_reset(join_tab->flush_weedout_table);
do_sj_reset(flush_dups_table);
}
if (!join_tab->preread_init_done && join_tab->preread_init())
......@@ -21033,7 +21028,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
extra.append(STRING_WITH_LEN("; LooseScan"));
}
if (tab->flush_weedout_table)
if (tab->first_weedout_table)
extra.append(STRING_WITH_LEN("; Start temporary"));
if (tab->check_weed_out_table)
extra.append(STRING_WITH_LEN("; End temporary"));
......
......@@ -158,6 +158,17 @@ enum enum_nested_loop_state
};
/* Possible sj_strategy values */
enum sj_strategy_enum
{
SJ_OPT_NONE=0,
SJ_OPT_DUPS_WEEDOUT=1,
SJ_OPT_LOOSE_SCAN =2,
SJ_OPT_FIRST_MATCH =3,
SJ_OPT_MATERIALIZE =4,
SJ_OPT_MATERIALIZE_SCAN=5
};
/* Values for JOIN_TAB::packed_info */
#define TAB_INFO_HAVE_VALUE 1
#define TAB_INFO_USING_INDEX 2
......@@ -330,6 +341,8 @@ typedef struct st_join_table {
/* Variables for semi-join duplicate elimination */
SJ_TMP_TABLE *flush_weedout_table;
SJ_TMP_TABLE *check_weed_out_table;
/* for EXPLAIN only: */
SJ_TMP_TABLE *first_weedout_table;
/*
If set, means we should stop join enumeration after we've got the first
......@@ -374,7 +387,7 @@ typedef struct st_join_table {
POSITION::sj_strategy field. This field is set up by the
fix_semijoin_strategies_for_picked_join_order.
*/
uint sj_strategy;
enum sj_strategy_enum sj_strategy;
uint n_sj_tables;
......@@ -500,6 +513,214 @@ enum_nested_loop_state
end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records);
/* psergey */
struct st_position;
class Semi_join_strategy_picker
{
public:
/* Called when starting to build a new join prefix */
virtual void set_empty() = 0;
/*
Update internal state after another table has been added to the join
prefix
*/
virtual void set_from_prev(struct st_position *prev) = 0;
virtual bool check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
const JOIN_TAB *new_join_tab,
double *record_count,
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
struct st_position *loose_scan_pos) = 0;
virtual void mark_used() = 0;
virtual ~Semi_join_strategy_picker() {}
};
/*
Duplicate Weedout strategy optimization state
*/
class Duplicate_weedout_picker : public Semi_join_strategy_picker
{
/* The first table that the strategy will need to handle */
uint first_dupsweedout_table;
/*
Tables that we will need to have in the prefix to do the weedout step
(all inner and all outer that the involved semi-joins are correlated with)
*/
table_map dupsweedout_tables;
bool is_used;
public:
void set_empty()
{
dupsweedout_tables= 0;
first_dupsweedout_table= MAX_TABLES;
is_used= FALSE;
}
void set_from_prev(struct st_position *prev);
bool check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
const JOIN_TAB *new_join_tab,
double *record_count,
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *stratey,
struct st_position *loose_scan_pos);
void mark_used() { is_used= TRUE; }
friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join);
};
class Firstmatch_picker : public Semi_join_strategy_picker
{
/*
Index of the first inner table that we intend to handle with this
strategy
*/
uint first_firstmatch_table;
/*
Tables that were not in the join prefix when we've started considering
FirstMatch strategy.
*/
table_map first_firstmatch_rtbl;
/*
Tables that need to be in the prefix before we can calculate the cost
of using FirstMatch strategy.
*/
table_map firstmatch_need_tables;
bool is_used;
bool in_firstmatch_prefix() { return (first_firstmatch_table != MAX_TABLES); }
void invalidate_firstmatch_prefix() { first_firstmatch_table= MAX_TABLES; }
public:
void set_empty()
{
invalidate_firstmatch_prefix();
is_used= FALSE;
}
void set_from_prev(struct st_position *prev);
bool check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
const JOIN_TAB *new_join_tab,
double *record_count,
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
struct st_position *loose_scan_pos);
void mark_used() { is_used= TRUE; }
friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join);
};
class LooseScan_picker : public Semi_join_strategy_picker
{
/* The first (i.e. driving) table we're doing loose scan for */
uint first_loosescan_table;
/*
Tables that need to be in the prefix before we can calculate the cost
of using LooseScan strategy.
*/
table_map loosescan_need_tables;
/*
keyno - Planning to do LooseScan on this key. If keyuse is NULL then
this is a full index scan, otherwise this is a ref+loosescan
scan (and keyno matches the KEUSE's)
MAX_KEY - Not doing a LooseScan
*/
uint loosescan_key; // final (one for strategy instance )
uint loosescan_parts; /* Number of keyparts to be kept distinct */
bool is_used;
public:
void set_empty()
{
first_loosescan_table= MAX_TABLES;
is_used= FALSE;
}
void set_from_prev(struct st_position *prev);
bool check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
const JOIN_TAB *new_join_tab,
double *record_count,
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
struct st_position *loose_scan_pos);
void mark_used() { is_used= TRUE; }
friend class Loose_scan_opt;
friend void best_access_path(JOIN *join,
JOIN_TAB *s,
table_map remaining_tables,
uint idx,
bool disable_jbuf,
double record_count,
struct st_position *pos,
struct st_position *loose_scan_pos);
friend bool get_best_combination(JOIN *join);
friend int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
uint no_jbuf_after);
friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join);
};
class Sj_materialization_picker : public Semi_join_strategy_picker
{
bool is_used;
/* The last inner table (valid once we're after it) */
uint sjm_scan_last_inner;
/*
Tables that we need to have in the prefix to calculate the correct cost.
Basically, we need all inner tables and outer tables mentioned in the
semi-join's ON expression so we can correctly account for fanout.
*/
table_map sjm_scan_need_tables;
public:
void set_empty()
{
sjm_scan_need_tables= 0;
LINT_INIT(sjm_scan_last_inner);
is_used= FALSE;
}
void set_from_prev(struct st_position *prev);
bool check_qep(JOIN *join,
uint idx,
table_map remaining_tables,
const JOIN_TAB *new_join_tab,
double *record_count,
double *read_time,
table_map *handled_fanout,
sj_strategy_enum *strategy,
struct st_position *loose_scan_pos);
void mark_used() { is_used= TRUE; }
friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join);
};
/**
Information about a position of table within a join order. Used in join
......@@ -507,6 +728,9 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
*/
typedef struct st_position
{
/* The table that's put into join order */
JOIN_TAB *table;
/*
The "fanout": number of output rows that will be produced (after
pushed down selection condition is applied) per each row combination of
......@@ -520,7 +744,10 @@ typedef struct st_position
number the access method will be invoked.
*/
double read_time;
JOIN_TAB *table;
/* Cumulative cost and record count for the join prefix */
COST_VECT prefix_cost;
double prefix_record_count;
/*
NULL - 'index' or 'range' or 'index_merge' or 'ALL' access is used.
......@@ -530,14 +757,13 @@ typedef struct st_position
/* If ref-based access is used: bitmap of tables this table depends on */
table_map ref_depend_map;
bool use_join_buffer;
/* These form a stack of partial join order costs and output sizes */
COST_VECT prefix_cost;
double prefix_record_count;
/*
TRUE <=> join buffering will be used. At the moment this is based on
*very* imprecise guesses made in best_access_path().
*/
bool use_join_buffer;
/*
Current optimization state: Semi-join strategy to be used for this
and preceding join tables.
......@@ -550,7 +776,8 @@ typedef struct st_position
this applies to. The values of covered_preceding_positions->sj_strategy
must be ignored.
*/
uint sj_strategy;
enum sj_strategy_enum sj_strategy;
/*
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
......@@ -558,67 +785,15 @@ typedef struct st_position
*/
uint n_sj_tables;
/* LooseScan strategy members */
/* The first (i.e. driving) table we're doing loose scan for */
uint first_loosescan_table;
/*
Tables that need to be in the prefix before we can calculate the cost
of using LooseScan strategy.
*/
table_map loosescan_need_tables;
/*
keyno - Planning to do LooseScan on this key. If keyuse is NULL then
this is a full index scan, otherwise this is a ref+loosescan
scan (and keyno matches the KEUSE's)
MAX_KEY - Not doing a LooseScan
*/
uint loosescan_key; // final (one for strategy instance )
uint loosescan_parts; /* Number of keyparts to be kept distinct */
/* FirstMatch strategy */
/*
Index of the first inner table that we intend to handle with this
strategy
*/
uint first_firstmatch_table;
/*
Tables that were not in the join prefix when we've started considering
FirstMatch strategy.
*/
table_map first_firstmatch_rtbl;
/*
Tables that need to be in the prefix before we can calculate the cost
of using FirstMatch strategy.
*/
table_map firstmatch_need_tables;
bool in_firstmatch_prefix() { return (first_firstmatch_table != MAX_TABLES); }
void invalidate_firstmatch_prefix() { first_firstmatch_table= MAX_TABLES; }
/* Duplicate Weedout strategy */
/* The first table that the strategy will need to handle */
uint first_dupsweedout_table;
/*
Tables that we will need to have in the prefix to do the weedout step
(all inner and all outer that the involved semi-joins are correlated with)
*/
table_map dupsweedout_tables;
/* SJ-Materialization-Scan strategy */
/* The last inner table (valid once we're after it) */
uint sjm_scan_last_inner;
/*
Tables that we need to have in the prefix to calculate the correct cost.
Basically, we need all inner tables and outer tables mentioned in the
semi-join's ON expression so we can correctly account for fanout.
*/
table_map sjm_scan_need_tables;
table_map prefix_dups_producing_tables;
} POSITION;
table_map inner_tables_handled_with_other_sjs;
Duplicate_weedout_picker dups_weedout_picker;
Firstmatch_picker firstmatch_picker;
LooseScan_picker loosescan_picker;
Sj_materialization_picker sjmat_picker;
} POSITION;
typedef struct st_rollup
{
......@@ -630,18 +805,6 @@ typedef struct st_rollup
} ROLLUP;
#define SJ_OPT_NONE 0
#define SJ_OPT_DUPS_WEEDOUT 1
#define SJ_OPT_LOOSE_SCAN 2
#define SJ_OPT_FIRST_MATCH 3
#define SJ_OPT_MATERIALIZE 4
#define SJ_OPT_MATERIALIZE_SCAN 5
inline bool sj_is_materialize_strategy(uint strategy)
{
return strategy >= SJ_OPT_MATERIALIZE;
}
class JOIN_TAB_RANGE: public Sql_alloc
{
public:
......@@ -812,7 +975,7 @@ class JOIN :public Sql_alloc
they produce.
*/
table_map cur_dups_producing_tables;
/* We also maintain a stack of join optimization states in * join->positions[] */
/******* Join optimization state members end *******/
/*
......
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