Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
440a803c
Commit
440a803c
authored
Oct 01, 2011
by
Sergey Petrunya
Browse files
Options
Browse Files
Download
Plain Diff
Merge
parents
2c120604
6e236b7b
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
183 additions
and
51 deletions
+183
-51
mysql-test/r/subselect_mat.result
mysql-test/r/subselect_mat.result
+25
-1
mysql-test/r/subselect_sj2_mat.result
mysql-test/r/subselect_sj2_mat.result
+1
-1
mysql-test/r/subselect_sj_mat.result
mysql-test/r/subselect_sj_mat.result
+25
-1
mysql-test/t/subselect_sj_mat.test
mysql-test/t/subselect_sj_mat.test
+32
-2
sql/opt_subselect.cc
sql/opt_subselect.cc
+79
-46
sql/sql_select.cc
sql/sql_select.cc
+20
-0
sql/sql_select.h
sql/sql_select.h
+1
-0
No files found.
mysql-test/r/subselect_mat.result
View file @
440a803c
...
@@ -1656,7 +1656,6 @@ a
...
@@ -1656,7 +1656,6 @@ a
0
0
0
0
DROP TABLE t2,t3,t4,t5;
DROP TABLE t2,t3,t4,t5;
set optimizer_switch=@subselect_sj_mat_tmp;
#
#
# BUG#860300: Second crash with get_fanout_with_deps() with semijoin + materialization
# BUG#860300: Second crash with get_fanout_with_deps() with semijoin + materialization
#
#
...
@@ -1703,6 +1702,31 @@ f3
...
@@ -1703,6 +1702,31 @@ f3
7
7
DROP TABLE t1, t2, t3, t4;
DROP TABLE t1, t2, t3, t4;
set optimizer_switch=@tmp_860535;
set optimizer_switch=@tmp_860535;
#
# BUG#860553: Crash in create_ref_for_key with semijoin + materialization
#
CREATE TABLE t1 (f1 int) ;
CREATE TABLE t2 (f5 varchar(52) NOT NULL) ;
CREATE TABLE t3 (f1 varchar(3), f4 varchar(52) , KEY (f4), PRIMARY KEY (f1));
CREATE TABLE t4 (f3 int, KEY (f3));
INSERT INTO t4 VALUES (17),(20);
CREATE TABLE t5 (f2 int);
INSERT INTO t5 VALUES (0),(0);
SELECT *
FROM t1
JOIN t2
ON ( t2.f5 ) IN (
SELECT t3.f4
FROM t3
WHERE ( 1 ) IN (
SELECT t4.f3
FROM t4 , t5
)
);
f1 f5
DROP TABLE t1, t2, t3, t4, t5;
# This must be at the end:
set optimizer_switch=@subselect_sj_mat_tmp;
set @subselect_mat_test_optimizer_switch_value=null;
set @subselect_mat_test_optimizer_switch_value=null;
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
...
...
mysql-test/r/subselect_sj2_mat.result
View file @
440a803c
...
@@ -593,7 +593,7 @@ select * from t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t3));
...
@@ -593,7 +593,7 @@ select * from t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t3));
id select_type table type possible_keys key key_len ref rows Extra
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where
2
DEPENDENT SUBQUERY t3 unique_subquery PRIMARY PRIMARY 4 func 1
Using index
2
SUBQUERY t3 index PRIMARY PRIMARY 4 NULL 10
Using index
drop table t0, t1, t2, t3;
drop table t0, t1, t2, t3;
create table t1 (a int);
create table t1 (a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
...
...
mysql-test/r/subselect_sj_mat.result
View file @
440a803c
...
@@ -1696,7 +1696,6 @@ a
...
@@ -1696,7 +1696,6 @@ a
0
0
0
0
DROP TABLE t2,t3,t4,t5;
DROP TABLE t2,t3,t4,t5;
set optimizer_switch=@subselect_sj_mat_tmp;
#
#
# BUG#860300: Second crash with get_fanout_with_deps() with semijoin + materialization
# BUG#860300: Second crash with get_fanout_with_deps() with semijoin + materialization
#
#
...
@@ -1743,3 +1742,28 @@ f3
...
@@ -1743,3 +1742,28 @@ f3
7
7
DROP TABLE t1, t2, t3, t4;
DROP TABLE t1, t2, t3, t4;
set optimizer_switch=@tmp_860535;
set optimizer_switch=@tmp_860535;
#
# BUG#860553: Crash in create_ref_for_key with semijoin + materialization
#
CREATE TABLE t1 (f1 int) ;
CREATE TABLE t2 (f5 varchar(52) NOT NULL) ;
CREATE TABLE t3 (f1 varchar(3), f4 varchar(52) , KEY (f4), PRIMARY KEY (f1));
CREATE TABLE t4 (f3 int, KEY (f3));
INSERT INTO t4 VALUES (17),(20);
CREATE TABLE t5 (f2 int);
INSERT INTO t5 VALUES (0),(0);
SELECT *
FROM t1
JOIN t2
ON ( t2.f5 ) IN (
SELECT t3.f4
FROM t3
WHERE ( 1 ) IN (
SELECT t4.f3
FROM t4 , t5
)
);
f1 f5
DROP TABLE t1, t2, t3, t4, t5;
# This must be at the end:
set optimizer_switch=@subselect_sj_mat_tmp;
mysql-test/t/subselect_sj_mat.test
View file @
440a803c
...
@@ -1349,8 +1349,6 @@ WHERE t2.a = ALL (
...
@@ -1349,8 +1349,6 @@ WHERE t2.a = ALL (
DROP
TABLE
t2
,
t3
,
t4
,
t5
;
DROP
TABLE
t2
,
t3
,
t4
,
t5
;
set
optimizer_switch
=@
subselect_sj_mat_tmp
;
--
echo
#
--
echo
#
--
echo
# BUG#860300: Second crash with get_fanout_with_deps() with semijoin + materialization
--
echo
# BUG#860300: Second crash with get_fanout_with_deps() with semijoin + materialization
--
echo
#
--
echo
#
...
@@ -1399,3 +1397,35 @@ SELECT * FROM t4;
...
@@ -1399,3 +1397,35 @@ SELECT * FROM t4;
DROP
TABLE
t1
,
t2
,
t3
,
t4
;
DROP
TABLE
t1
,
t2
,
t3
,
t4
;
set
optimizer_switch
=@
tmp_860535
;
set
optimizer_switch
=@
tmp_860535
;
--
echo
#
--
echo
# BUG#860553: Crash in create_ref_for_key with semijoin + materialization
--
echo
#
CREATE
TABLE
t1
(
f1
int
)
;
CREATE
TABLE
t2
(
f5
varchar
(
52
)
NOT
NULL
)
;
CREATE
TABLE
t3
(
f1
varchar
(
3
),
f4
varchar
(
52
)
,
KEY
(
f4
),
PRIMARY
KEY
(
f1
));
CREATE
TABLE
t4
(
f3
int
,
KEY
(
f3
));
INSERT
INTO
t4
VALUES
(
17
),(
20
);
CREATE
TABLE
t5
(
f2
int
);
INSERT
INTO
t5
VALUES
(
0
),(
0
);
SELECT
*
FROM
t1
JOIN
t2
ON
(
t2
.
f5
)
IN
(
SELECT
t3
.
f4
FROM
t3
WHERE
(
1
)
IN
(
SELECT
t4
.
f3
FROM
t4
,
t5
)
);
DROP
TABLE
t1
,
t2
,
t3
,
t4
,
t5
;
--
echo
# This must be at the end:
set
optimizer_switch
=@
subselect_sj_mat_tmp
;
sql/opt_subselect.cc
View file @
440a803c
...
@@ -209,6 +209,74 @@ enum_nested_loop_state
...
@@ -209,6 +209,74 @@ enum_nested_loop_state
end_sj_materialize
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
end_of_records
);
end_sj_materialize
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
end_of_records
);
/*
Check if Materialization strategy is allowed for given subquery predicate.
@param thd Thread handle
@param in_subs The subquery predicate
@param child_select The select inside predicate (the function will
check it is the only one)
@return TRUE - Materialization is applicable
FALSE - Otherwise
*/
bool
is_materialization_applicable
(
THD
*
thd
,
Item_in_subselect
*
in_subs
,
st_select_lex
*
child_select
)
{
st_select_lex_unit
*
parent_unit
=
child_select
->
master_unit
();
/*
Check if the subquery predicate can be executed via materialization.
The required conditions are:
0. The materialization optimizer switch was set.
1. Subquery is a single SELECT (not a UNION).
TODO: this is a limitation that can be fixed
2. Subquery is not a table-less query. In this case there is no
point in materializing.
2A The upper query is not a table-less SELECT ... FROM DUAL. We
can't do materialization for SELECT .. FROM DUAL because it
does not call setup_subquery_materialization(). We could make
SELECT ... FROM DUAL call that function but that doesn't seem
to be the case that is worth handling.
3. Either the subquery predicate is a top-level predicate, or at
least one partial match strategy is enabled. If no partial match
strategy is enabled, then materialization cannot be used for
non-top-level queries because it cannot handle NULLs correctly.
4. Subquery is non-correlated
TODO:
This condition is too restrictive (limitation). It can be extended to:
(Subquery is non-correlated ||
Subquery is correlated to any query outer to IN predicate ||
(Subquery is correlated to the immediate outer query &&
Subquery !contains {GROUP BY, ORDER BY [LIMIT],
aggregate functions}) && subquery predicate is not under "NOT IN"))
(*) The subquery must be part of a SELECT statement. The current
condition also excludes multi-table update statements.
A note about prepared statements: we want the if-branch to be taken on
PREPARE and each EXECUTE. The rewrites are only done once, but we need
select_lex->sj_subselects list to be populated for every EXECUTE.
*/
if
(
optimizer_flag
(
thd
,
OPTIMIZER_SWITCH_MATERIALIZATION
)
&&
// 0
!
child_select
->
is_part_of_union
()
&&
// 1
parent_unit
->
first_select
()
->
leaf_tables
.
elements
&&
// 2
thd
->
lex
->
sql_command
==
SQLCOM_SELECT
&&
// *
child_select
->
outer_select
()
->
leaf_tables
.
elements
&&
// 2A
subquery_types_allow_materialization
(
in_subs
)
&&
(
in_subs
->
is_top_level_item
()
||
//3
optimizer_flag
(
thd
,
OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE
)
||
//3
optimizer_flag
(
thd
,
OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN
))
&&
//3
!
in_subs
->
is_correlated
)
//4
{
return
TRUE
;
}
return
FALSE
;
}
/*
/*
Check if we need JOIN::prepare()-phase subquery rewrites and if yes, do them
Check if we need JOIN::prepare()-phase subquery rewrites and if yes, do them
...
@@ -381,52 +449,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
...
@@ -381,52 +449,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
*/
*/
if
(
in_subs
)
if
(
in_subs
)
{
{
/*
if
(
is_materialization_applicable
(
thd
,
in_subs
,
select_lex
))
Check if the subquery predicate can be executed via materialization.
{
The required conditions are:
0. The materialization optimizer switch was set.
1. Subquery is a single SELECT (not a UNION).
TODO: this is a limitation that can be fixed
2. Subquery is not a table-less query. In this case there is no
point in materializing.
2A The upper query is not a table-less SELECT ... FROM DUAL. We
can't do materialization for SELECT .. FROM DUAL because it
does not call setup_subquery_materialization(). We could make
SELECT ... FROM DUAL call that function but that doesn't seem
to be the case that is worth handling.
3. Either the subquery predicate is a top-level predicate, or at
least one partial match strategy is enabled. If no partial match
strategy is enabled, then materialization cannot be used for
non-top-level queries because it cannot handle NULLs correctly.
4. Subquery is non-correlated
TODO:
This condition is too restrictive (limitation). It can be extended to:
(Subquery is non-correlated ||
Subquery is correlated to any query outer to IN predicate ||
(Subquery is correlated to the immediate outer query &&
Subquery !contains {GROUP BY, ORDER BY [LIMIT],
aggregate functions}) && subquery predicate is not under "NOT IN"))
(*) The subquery must be part of a SELECT statement. The current
condition also excludes multi-table update statements.
A note about prepared statements: we want the if-branch to be taken on
PREPARE and each EXECUTE. The rewrites are only done once, but we need
select_lex->sj_subselects list to be populated for every EXECUTE.
*/
if
(
optimizer_flag
(
thd
,
OPTIMIZER_SWITCH_MATERIALIZATION
)
&&
// 0
!
select_lex
->
is_part_of_union
()
&&
// 1
parent_unit
->
first_select
()
->
leaf_tables
.
elements
&&
// 2
thd
->
lex
->
sql_command
==
SQLCOM_SELECT
&&
// *
select_lex
->
outer_select
()
->
leaf_tables
.
elements
&&
// 2A
subquery_types_allow_materialization
(
in_subs
)
&&
(
in_subs
->
is_top_level_item
()
||
//3
optimizer_flag
(
thd
,
OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE
)
||
//3
optimizer_flag
(
thd
,
OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN
))
&&
//3
!
in_subs
->
is_correlated
)
//4
{
in_subs
->
in_strategy
|=
SUBS_MATERIALIZATION
;
in_subs
->
in_strategy
|=
SUBS_MATERIALIZATION
;
/*
/*
...
@@ -914,6 +938,12 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
...
@@ -914,6 +938,12 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
check_and_do_in_subquery_rewrites.
check_and_do_in_subquery_rewrites.
*/
*/
in_subq
->
in_strategy
=
SUBS_IN_TO_EXISTS
;
in_subq
->
in_strategy
=
SUBS_IN_TO_EXISTS
;
if
(
is_materialization_applicable
(
thd
,
in_subq
,
in_subq
->
unit
->
first_select
()))
{
in_subq
->
in_strategy
|=
SUBS_MATERIALIZATION
;
}
in_subq
=
li
++
;
in_subq
=
li
++
;
}
}
...
@@ -1766,6 +1796,9 @@ int pull_out_semijoin_tables(JOIN *join)
...
@@ -1766,6 +1796,9 @@ int pull_out_semijoin_tables(JOIN *join)
All obtained information is saved and will be used by the main join
All obtained information is saved and will be used by the main join
optimization pass.
optimization pass.
NOTES
Because of Join::reoptimize(), this function may be called multiple times.
RETURN
RETURN
FALSE Ok
FALSE Ok
...
...
sql/sql_select.cc
View file @
440a803c
...
@@ -21576,6 +21576,15 @@ void JOIN::save_query_plan(Join_plan_state *save_to)
...
@@ -21576,6 +21576,15 @@ void JOIN::save_query_plan(Join_plan_state *save_to)
memcpy
((
uchar
*
)
save_to
->
best_positions
,
(
uchar
*
)
best_positions
,
memcpy
((
uchar
*
)
save_to
->
best_positions
,
(
uchar
*
)
best_positions
,
sizeof
(
POSITION
)
*
(
table_count
+
1
));
sizeof
(
POSITION
)
*
(
table_count
+
1
));
memset
(
best_positions
,
0
,
sizeof
(
POSITION
)
*
(
table_count
+
1
));
memset
(
best_positions
,
0
,
sizeof
(
POSITION
)
*
(
table_count
+
1
));
/* Save SJM nests */
List_iterator
<
TABLE_LIST
>
it
(
select_lex
->
sj_nests
);
TABLE_LIST
*
tlist
;
SJ_MATERIALIZATION_INFO
**
p_info
=
save_to
->
sj_mat_info
;
while
((
tlist
=
it
++
))
{
*
(
p_info
++
)
=
tlist
->
sj_mat_info
;
}
}
}
...
@@ -21616,6 +21625,14 @@ void JOIN::restore_query_plan(Join_plan_state *restore_from)
...
@@ -21616,6 +21625,14 @@ void JOIN::restore_query_plan(Join_plan_state *restore_from)
}
}
memcpy
((
uchar
*
)
best_positions
,
(
uchar
*
)
restore_from
->
best_positions
,
memcpy
((
uchar
*
)
best_positions
,
(
uchar
*
)
restore_from
->
best_positions
,
sizeof
(
POSITION
)
*
(
table_count
+
1
));
sizeof
(
POSITION
)
*
(
table_count
+
1
));
/* Restore SJM nests */
List_iterator
<
TABLE_LIST
>
it
(
select_lex
->
sj_nests
);
TABLE_LIST
*
tlist
;
SJ_MATERIALIZATION_INFO
**
p_info
=
restore_from
->
sj_mat_info
;
while
((
tlist
=
it
++
))
{
tlist
->
sj_mat_info
=
*
(
p_info
++
);
}
}
}
...
@@ -21705,6 +21722,9 @@ JOIN::reoptimize(Item *added_where, table_map join_tables,
...
@@ -21705,6 +21722,9 @@ JOIN::reoptimize(Item *added_where, table_map join_tables,
return
REOPT_ERROR
;
return
REOPT_ERROR
;
optimize_keyuse
(
this
,
&
keyuse
);
optimize_keyuse
(
this
,
&
keyuse
);
if
(
optimize_semijoin_nests
(
this
,
join_tables
))
return
REOPT_ERROR
;
/* Re-run the join optimizer to compute a new query plan. */
/* Re-run the join optimizer to compute a new query plan. */
if
(
choose_plan
(
this
,
join_tables
))
if
(
choose_plan
(
this
,
join_tables
))
return
REOPT_ERROR
;
return
REOPT_ERROR
;
...
...
sql/sql_select.h
View file @
440a803c
...
@@ -666,6 +666,7 @@ class JOIN :public Sql_alloc
...
@@ -666,6 +666,7 @@ class JOIN :public Sql_alloc
KEYUSE
*
join_tab_keyuse
[
MAX_TABLES
];
KEYUSE
*
join_tab_keyuse
[
MAX_TABLES
];
/* Copies of JOIN_TAB::checked_keys for each JOIN_TAB. */
/* Copies of JOIN_TAB::checked_keys for each JOIN_TAB. */
key_map
join_tab_checked_keys
[
MAX_TABLES
];
key_map
join_tab_checked_keys
[
MAX_TABLES
];
SJ_MATERIALIZATION_INFO
*
sj_mat_info
[
MAX_TABLES
];
public:
public:
Join_plan_state
()
Join_plan_state
()
{
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment