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
|
||||
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
|
||||
#
|
||||
@ -1703,6 +1702,31 @@ f3
|
||||
7
|
||||
DROP TABLE t1, t2, t3, t4;
|
||||
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 @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
|
||||
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
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
|
||||
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;
|
||||
create table t1 (a int);
|
||||
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||
|
@ -1696,7 +1696,6 @@ a
|
||||
0
|
||||
0
|
||||
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
|
||||
#
|
||||
@ -1743,3 +1742,28 @@ f3
|
||||
7
|
||||
DROP TABLE t1, t2, t3, t4;
|
||||
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;
|
||||
|
||||
set optimizer_switch=@subselect_sj_mat_tmp;
|
||||
|
||||
--echo #
|
||||
--echo # BUG#860300: Second crash with get_fanout_with_deps() with semijoin + materialization
|
||||
--echo #
|
||||
@ -1399,3 +1397,35 @@ SELECT * FROM t4;
|
||||
DROP TABLE t1, t2, t3, t4;
|
||||
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);
|
||||
|
||||
|
||||
/*
|
||||
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
|
||||
|
||||
@ -381,52 +449,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
|
||||
*/
|
||||
if (in_subs)
|
||||
{
|
||||
/*
|
||||
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
|
||||
{
|
||||
if (is_materialization_applicable(thd, in_subs, select_lex))
|
||||
{
|
||||
in_subs->in_strategy|= SUBS_MATERIALIZATION;
|
||||
|
||||
/*
|
||||
@ -914,6 +938,12 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
|
||||
check_and_do_in_subquery_rewrites.
|
||||
*/
|
||||
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++;
|
||||
}
|
||||
|
||||
@ -1767,6 +1797,9 @@ int pull_out_semijoin_tables(JOIN *join)
|
||||
All obtained information is saved and will be used by the main join
|
||||
optimization pass.
|
||||
|
||||
NOTES
|
||||
Because of Join::reoptimize(), this function may be called multiple times.
|
||||
|
||||
RETURN
|
||||
FALSE Ok
|
||||
TRUE Out of memory error
|
||||
|
@ -21576,6 +21576,15 @@ void JOIN::save_query_plan(Join_plan_state *save_to)
|
||||
memcpy((uchar*) save_to->best_positions, (uchar*) best_positions,
|
||||
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,
|
||||
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;
|
||||
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. */
|
||||
if (choose_plan(this, join_tables))
|
||||
return REOPT_ERROR;
|
||||
|
@ -666,6 +666,7 @@ protected:
|
||||
KEYUSE *join_tab_keyuse[MAX_TABLES];
|
||||
/* Copies of JOIN_TAB::checked_keys for each JOIN_TAB. */
|
||||
key_map join_tab_checked_keys[MAX_TABLES];
|
||||
SJ_MATERIALIZATION_INFO *sj_mat_info[MAX_TABLES];
|
||||
public:
|
||||
Join_plan_state()
|
||||
{
|
||||
|
Reference in New Issue
Block a user