mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge
This commit is contained in:
@ -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
|
|||||||
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';
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
|||||||
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;
|
||||||
|
@ -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;
|
|||||||
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;
|
||||||
|
|
||||||
|
@ -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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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
|
||||||
|
@ -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)
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
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;
|
||||||
|
@ -666,6 +666,7 @@ protected:
|
|||||||
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()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user