Commit d2cbb104 authored by Sergey Petrunya's avatar Sergey Petrunya

Backport of (see below) + temporary measures to make SJ-Materialization work with join buffering.

Date: Mon, 01 Nov 2010 15:15:25 -0000
3272 Roy Lyseng        2010-11-01
Bug#52068: Optimizer generates invalid semijoin materialization plan

When MaterializeScan semijoin strategy was used and there were one
or more outer dependent tables before the semijoin tables, the scan
over the materialized table was not properly reset for each row of
the prefix outer tables.

Example: suppose we have a join order:

  ot1 SJ-Mat-Scan(it2 it3)  ot4

Notice that this is called a MaterializeScan, even though there is an
outer table ahead of the materialized tables. Usually a MaterializeScan
has the outer tables after the materialized table, but this is
a special (but legal) case with outer dependent tables both before and
after the materialized table.

For each qualifying row from ot1, a new scan over the materialized
table must be set up. The code failed to do that, so all scans after
the first one returned zero rows from the materialized table.
parent 959bf3c1
No related merge requests found
...@@ -4975,3 +4975,39 @@ k ...@@ -4975,3 +4975,39 @@ k
3 3
drop table t1,t2,t3; drop table t1,t2,t3;
drop view v2; drop view v2;
#
# Bug#52068: Optimizer generates invalid semijoin materialization plan
#
drop table if exists ot1, ot2, it1, it2;
CREATE TABLE ot1(a INTEGER);
INSERT INTO ot1 VALUES(5), (8);
CREATE TABLE it2(a INTEGER);
INSERT INTO it2 VALUES(9), (5), (1), (8);
CREATE TABLE it3(a INTEGER);
INSERT INTO it3 VALUES(7), (1), (0), (5), (1), (4);
CREATE TABLE ot4(a INTEGER);
INSERT INTO ot4 VALUES(1), (3), (5), (7), (9), (7), (3), (1);
SELECT * FROM ot1,ot4
WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
a a
5 1
8 1
5 5
8 5
5 7
8 7
5 7
8 7
5 1
8 1
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
1 PRIMARY subselect2 ALL unique_key NULL NULL NULL 24
1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
2 SUBQUERY it2 ALL NULL NULL NULL NULL 4
2 SUBQUERY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
...@@ -4978,6 +4978,41 @@ k ...@@ -4978,6 +4978,41 @@ k
3 3
drop table t1,t2,t3; drop table t1,t2,t3;
drop view v2; drop view v2;
#
# Bug#52068: Optimizer generates invalid semijoin materialization plan
#
drop table if exists ot1, ot2, it1, it2;
CREATE TABLE ot1(a INTEGER);
INSERT INTO ot1 VALUES(5), (8);
CREATE TABLE it2(a INTEGER);
INSERT INTO it2 VALUES(9), (5), (1), (8);
CREATE TABLE it3(a INTEGER);
INSERT INTO it3 VALUES(7), (1), (0), (5), (1), (4);
CREATE TABLE ot4(a INTEGER);
INSERT INTO ot4 VALUES(1), (3), (5), (7), (9), (7), (3), (1);
SELECT * FROM ot1,ot4
WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
a a
5 1
8 1
5 5
8 5
5 7
8 7
5 7
8 7
5 1
8 1
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 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;
set optimizer_switch=default; set optimizer_switch=default;
select @@optimizer_switch like '%materialization=on%'; select @@optimizer_switch like '%materialization=on%';
@@optimizer_switch like '%materialization=on%' @@optimizer_switch like '%materialization=on%'
......
...@@ -4975,4 +4975,39 @@ k ...@@ -4975,4 +4975,39 @@ k
3 3
drop table t1,t2,t3; drop table t1,t2,t3;
drop view v2; drop view v2;
#
# Bug#52068: Optimizer generates invalid semijoin materialization plan
#
drop table if exists ot1, ot2, it1, it2;
CREATE TABLE ot1(a INTEGER);
INSERT INTO ot1 VALUES(5), (8);
CREATE TABLE it2(a INTEGER);
INSERT INTO it2 VALUES(9), (5), (1), (8);
CREATE TABLE it3(a INTEGER);
INSERT INTO it3 VALUES(7), (1), (0), (5), (1), (4);
CREATE TABLE ot4(a INTEGER);
INSERT INTO ot4 VALUES(1), (3), (5), (7), (9), (7), (3), (1);
SELECT * FROM ot1,ot4
WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
a a
5 1
8 1
5 5
8 5
5 7
8 7
5 7
8 7
5 1
8 1
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
1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
2 DEPENDENT SUBQUERY it2 ALL NULL NULL NULL NULL 4 Using where
2 DEPENDENT SUBQUERY it3 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
set optimizer_switch=default; set optimizer_switch=default;
...@@ -4975,4 +4975,39 @@ k ...@@ -4975,4 +4975,39 @@ k
3 3
drop table t1,t2,t3; drop table t1,t2,t3;
drop view v2; drop view v2;
#
# Bug#52068: Optimizer generates invalid semijoin materialization plan
#
drop table if exists ot1, ot2, it1, it2;
CREATE TABLE ot1(a INTEGER);
INSERT INTO ot1 VALUES(5), (8);
CREATE TABLE it2(a INTEGER);
INSERT INTO it2 VALUES(9), (5), (1), (8);
CREATE TABLE it3(a INTEGER);
INSERT INTO it3 VALUES(7), (1), (0), (5), (1), (4);
CREATE TABLE ot4(a INTEGER);
INSERT INTO ot4 VALUES(1), (3), (5), (7), (9), (7), (3), (1);
SELECT * FROM ot1,ot4
WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
a a
5 1
8 1
5 5
8 5
5 7
8 7
5 7
8 7
5 1
8 1
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
1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
2 SUBQUERY it2 ALL NULL NULL NULL NULL 4
2 SUBQUERY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
set optimizer_switch=default; set optimizer_switch=default;
...@@ -4251,3 +4251,30 @@ select * from t3 where k in (select j from v2); ...@@ -4251,3 +4251,30 @@ select * from t3 where k in (select j from v2);
drop table t1,t2,t3; drop table t1,t2,t3;
drop view v2; drop view v2;
--echo #
--echo # Bug#52068: Optimizer generates invalid semijoin materialization plan
--echo #
--disable_warnings
drop table if exists ot1, ot2, it1, it2;
--enable_warnings
CREATE TABLE ot1(a INTEGER);
INSERT INTO ot1 VALUES(5), (8);
CREATE TABLE it2(a INTEGER);
INSERT INTO it2 VALUES(9), (5), (1), (8);
CREATE TABLE it3(a INTEGER);
INSERT INTO it3 VALUES(7), (1), (0), (5), (1), (4);
CREATE TABLE ot4(a INTEGER);
INSERT INTO ot4 VALUES(1), (3), (5), (7), (9), (7), (3), (1);
let $query=
SELECT * FROM ot1,ot4
WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
eval $query;
eval explain $query;
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
...@@ -169,9 +169,17 @@ JOIN_TAB *JOIN_CACHE::get_next_table(JOIN_TAB *tab) ...@@ -169,9 +169,17 @@ JOIN_TAB *JOIN_CACHE::get_next_table(JOIN_TAB *tab)
if (join_tab->first_sjm_sibling) if (join_tab->first_sjm_sibling)
return tab; return tab;
uint i= tab-join->join_tab; uint i= tab-join->join_tab;
/*
Temporary measure before MWL#90 refactorings are there: if 'tab' is at upper
level (i.e. it's not inside an SJM nest), still include into the join buffer
the tables from within SJM nest. We might need the subquery's select list
columns, because SJ-Materialization-Scan upacks data to those.
while (sj_is_materialize_strategy(join->best_positions[i].sj_strategy) && while (sj_is_materialize_strategy(join->best_positions[i].sj_strategy) &&
i < join->tables) i < join->tables)
i+= join->best_positions[i].n_sj_tables; i+= join->best_positions[i].n_sj_tables;
*/
return join->join_tab+i < join_tab ? join->join_tab+i : NULL; return join->join_tab+i < join_tab ? join->join_tab+i : NULL;
} }
......
...@@ -13168,6 +13168,15 @@ sub_select_sjm(JOIN *join, JOIN_TAB *join_tab, bool end_of_records) ...@@ -13168,6 +13168,15 @@ sub_select_sjm(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
last_tab->read_record.read_record= rr_sequential_and_unpack; last_tab->read_record.read_record= rr_sequential_and_unpack;
} }
} }
else
{
if (sjm->is_sj_scan)
{
/* Reset the cursor for a new scan over the table */
if (sjm->table->file->ha_rnd_init(TRUE))
DBUG_RETURN(NESTED_LOOP_ERROR);
}
}
if (sjm->is_sj_scan) if (sjm->is_sj_scan)
{ {
......
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