Skip to content
Permalink
Browse files
Post review changes for the optimization of IN predicates into IN sub…
…queries.
  • Loading branch information
Galina Shalygina committed Sep 2, 2017
1 parent d76f74d commit 6bce8e1
Show file tree
Hide file tree
Showing 10 changed files with 306 additions and 147 deletions.
@@ -6,29 +6,26 @@ create table t2 (a int, b int, c int);
insert into t2
values (1,2,3), (5,1,2), (4,3,7),
(8,9,0), (10,7,1), (5,5,1);
create table t3 (a int, b varchar(16), index idx(a));
insert into t3 values
(1, "abc"), (3, "egh"), (8, "axxx"), (10, "abc"),
(2, "ccw"), (8, "wqqe"), (7, "au"), (9, "waa"),
(3, "rass"), (9, "ert"), (9, "lok"), (8, "aww"),
(1, "todd"), (3, "rew"), (8, "aww"), (3, "sw"),
(11, "llk"), (7, "rbw"), (1, "sm"), (2, "jyp"),
(4, "yq"), (5, "pled"), (12, "ligin"), (12, "toww"),
(6, "mxm"), (15, "wanone"), (9, "sunqq"), (2, "abe");
# optimization is not used
select * from t1 where a in (1,2);
a b
1 2
1 1
2 5
explain select * from t1 where a in (1,2);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using where
explain format=json select * from t1 where a in (1,2);
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 6,
"filtered": 100,
"attached_condition": "t1.a in (1,2)"
}
}
}
explain extended select * from t1 where a in (1,2);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` in (1,2)
# set minimum number of values in VALUEs list when optimization works to 2
set @@in_subquery_conversion_threshold= 2;
# single IN-predicate in WHERE-part
@@ -481,5 +478,68 @@ a b
1 1
2 5
deallocate prepare stmt;
drop table t1, t2;
# use inside out access from tvc rows
set @@in_subquery_conversion_threshold= default;
select * from t3 where a in (1,4,10);
a b
1 abc
1 todd
1 sm
4 yq
10 abc
explain extended select * from t3 where a in (1,4,10);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t3 range idx idx 5 NULL 5 100.00 Using index condition
Warnings:
Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` where `test`.`t3`.`a` in (1,4,10)
set @@in_subquery_conversion_threshold= 2;
select * from t3 where a in (1,4,10);
a b
1 abc
1 todd
1 sm
4 yq
10 abc
explain extended select * from t3 where a in (1,4,10);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
1 PRIMARY t3 ref idx idx 5 tvc_0.1 3 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` semi join ((values (1),(4),(10)) `tvc_0`) where `test`.`t3`.`a` = `tvc_0`.`1`
# use vectors in IN predeicate
set @@in_subquery_conversion_threshold= 4;
select * from t1 where (a,b) in ((1,2),(3,4));
a b
1 2
explain extended select * from t1 where (a,b) in ((1,2),(3,4));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1,2),(3,4)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1` and `test`.`t1`.`b` = `tvc_0`.`2`
set @@in_subquery_conversion_threshold= 2;
# trasformation works for the one IN predicate and doesn't work for the other
set @@in_subquery_conversion_threshold= 5;
select * from t2
where (a,b) in ((1,2),(8,9)) and
(a,c) in ((1,3),(8,0),(5,1));
a b c
1 2 3
8 9 0
explain extended select * from t2
where (a,b) in ((1,2),(8,9)) and
(a,c) in ((1,3),(8,0),(5,1));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where `test`.`t2`.`a` = `tvc_0`.`1` and `test`.`t2`.`c` = `tvc_0`.`3` and (`tvc_0`.`1`,`test`.`t2`.`b`) in (<cache>((1,2)),<cache>((8,9)))
set @@in_subquery_conversion_threshold= 2;
drop table t1, t2, t3;
set @@in_subquery_conversion_threshold= default;
@@ -10,12 +10,21 @@ insert into t2
values (1,2,3), (5,1,2), (4,3,7),
(8,9,0), (10,7,1), (5,5,1);

create table t3 (a int, b varchar(16), index idx(a));
insert into t3 values
(1, "abc"), (3, "egh"), (8, "axxx"), (10, "abc"),
(2, "ccw"), (8, "wqqe"), (7, "au"), (9, "waa"),
(3, "rass"), (9, "ert"), (9, "lok"), (8, "aww"),
(1, "todd"), (3, "rew"), (8, "aww"), (3, "sw"),
(11, "llk"), (7, "rbw"), (1, "sm"), (2, "jyp"),
(4, "yq"), (5, "pled"), (12, "ligin"), (12, "toww"),
(6, "mxm"), (15, "wanone"), (9, "sunqq"), (2, "abe");

--echo # optimization is not used

let $query= select * from t1 where a in (1,2);
eval $query;
eval explain $query;
eval explain format=json $query;
eval explain extended $query;

--echo # set minimum number of values in VALUEs list when optimization works to 2

@@ -239,5 +248,39 @@ execute stmt;
execute stmt;
deallocate prepare stmt;

drop table t1, t2;
--echo # use inside out access from tvc rows

let $query= select * from t3 where a in (1,4,10);
set @@in_subquery_conversion_threshold= default;
eval $query;
eval explain extended $query;
set @@in_subquery_conversion_threshold= 2;
eval $query;
eval explain extended $query;

--echo # use vectors in IN predeicate

set @@in_subquery_conversion_threshold= 4;

let $query=
select * from t1 where (a,b) in ((1,2),(3,4));

eval $query;
eval explain extended $query;
set @@in_subquery_conversion_threshold= 2;

--echo # trasformation works for the one IN predicate and doesn't work for the other

set @@in_subquery_conversion_threshold= 5;

let $query=
select * from t2
where (a,b) in ((1,2),(8,9)) and
(a,c) in ((1,3),(8,0),(5,1));

eval $query;
eval explain extended $query;
set @@in_subquery_conversion_threshold= 2;

drop table t1, t2, t3;
set @@in_subquery_conversion_threshold= default;
@@ -4334,8 +4334,11 @@ void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding)
Query_arena *arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup);

if (can_be_transformed_in_tvc(thd))
if (to_be_transformed_into_in_subq(thd))
{
transform_into_subq= true;
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
}

if (arena)
thd->restore_active_arena(arena, &backup);
@@ -2128,6 +2128,7 @@ class Item_func_in :public Item_func_opt_neg,
protected:
SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
Field *field, Item *value);
bool transform_into_subq;
public:
/// An array of values, created when the bisection lookup method is used
in_vector *array;
@@ -2244,7 +2245,8 @@ class Item_func_in :public Item_func_opt_neg,
return clone;
}
void mark_as_condition_AND_part(TABLE_LIST *embedding);
bool can_be_transformed_in_tvc(THD *thd);
bool to_be_transformed_into_in_subq(THD *thd);
bool create_value_list_for_tvc(THD *thd, List< List<Item> > *values);
Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg);
};

@@ -1047,7 +1047,7 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
DBUG_RETURN(1);
if (subq_sel->handle_derived(thd->lex, DT_MERGE))
DBUG_RETURN(TRUE);
if (subq_sel->join->transform_in_predicate_into_tvc(thd))
if (subq_sel->join->transform_in_predicates_into_in_subq(thd))
DBUG_RETURN(TRUE);
subq_sel->update_used_tables();
}
@@ -2265,7 +2265,7 @@ void st_select_lex::init_select()
lock_type= TL_READ_DEFAULT;
tvc= 0;
in_funcs.empty();
cur_tvc= 0;
curr_tvc_name= 0;
}

/*
@@ -874,7 +874,7 @@ class st_select_lex: public st_select_lex_node
transformation of IN-predicate into IN-subquery for this
st_select_lex.
*/
uint cur_tvc;
uint curr_tvc_name;

/*
Needed to correctly generate 'PRIMARY' or 'SIMPLE' for select_type column
@@ -1189,7 +1189,7 @@ JOIN::optimize_inner()
}

if (select_lex->first_cond_optimization &&
transform_in_predicate_into_tvc(thd))
transform_in_predicates_into_in_subq(thd))
DBUG_RETURN(1);

// Update used tables after all handling derived table procedures
@@ -1648,7 +1648,7 @@ class JOIN :public Sql_alloc
bool need_order, bool distinct,
const char *message);
JOIN_TAB *first_breadth_first_tab() { return join_tab; }
bool transform_in_predicate_into_tvc(THD *thd_arg);
bool transform_in_predicates_into_in_subq(THD *thd);
private:
/**
Create a temporary table to be used for processing DISTINCT/ORDER

0 comments on commit 6bce8e1

Please sign in to comment.