Commit b2c57ced authored by Sergey Petrunya's avatar Sergey Petrunya

Code cleanup in subquery optimizations

parent 30bac798
...@@ -382,8 +382,20 @@ class Item_in_subselect :public Item_exists_subselect ...@@ -382,8 +382,20 @@ class Item_in_subselect :public Item_exists_subselect
}; };
enum_exec_method exec_method; enum_exec_method exec_method;
/* JTBM: temporary measure to tell JTBM predicates from SJ predicates */ /*
JTBM: temporary measure to tell JTBM predicates from SJ predicates
psergey-jtbm-todo: can't we do without this?
- either remove it altogether
- or put into enum_exec_method
We can't remove it altogether as it is used to classify contents in
join->sj_subselects.
*/
bool convert_to_semi_join; bool convert_to_semi_join;
/*
Cost to populate the temporary table (set on if-needed basis).
*/
double startup_cost; double startup_cost;
bool *get_cond_guard(int i) bool *get_cond_guard(int i)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
@file @file
@brief @brief
Subquery optimization code here. Semi-join subquery optimizations code
*/ */
...@@ -228,15 +228,17 @@ int check_and_do_in_subquery_rewrites(JOIN *join) ...@@ -228,15 +228,17 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
if (in_subs->exec_method == Item_in_subselect::NOT_TRANSFORMED) if (in_subs->exec_method == Item_in_subselect::NOT_TRANSFORMED)
in_subs->exec_method= Item_in_subselect::MATERIALIZATION; in_subs->exec_method= Item_in_subselect::MATERIALIZATION;
// psergey-jtbm: "if we're top-level, register for /*
// conversion-to-join-tab". If the subquery is an AND-part of WHERE register for being processed
with jtbm strategy
*/
if (in_subs->exec_method == Item_in_subselect::MATERIALIZATION && if (in_subs->exec_method == Item_in_subselect::MATERIALIZATION &&
thd->thd_marker.emb_on_expr_nest == (TABLE_LIST*)0x1) thd->thd_marker.emb_on_expr_nest == (TABLE_LIST*)0x1)
{ {
in_subs->emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest; in_subs->emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
in_subs->convert_to_semi_join= FALSE; //JTBM in_subs->convert_to_semi_join= FALSE;
select_lex->outer_select()-> select_lex->outer_select()->
join->sj_subselects.append(thd->mem_root, in_subs);//JTBM join->sj_subselects.append(thd->mem_root, in_subs);
} }
} }
...@@ -406,6 +408,8 @@ static bool make_in_exists_conversion(THD *thd, JOIN *join, Item_in_subselect *i ...@@ -406,6 +408,8 @@ static bool make_in_exists_conversion(THD *thd, JOIN *join, Item_in_subselect *i
} }
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
/* /*
Convert semi-join subquery predicates into semi-join join nests Convert semi-join subquery predicates into semi-join join nests
...@@ -513,29 +517,6 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) ...@@ -513,29 +517,6 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
// #tables-in-parent-query + #tables-in-subquery < MAX_TABLES // #tables-in-parent-query + #tables-in-subquery < MAX_TABLES
/* Replace all subqueries to be flattened with Item_int(1) */ /* Replace all subqueries to be flattened with Item_int(1) */
arena= thd->activate_stmt_arena_if_needed(&backup); arena= thd->activate_stmt_arena_if_needed(&backup);
#if 0
for (in_subq= join->sj_subselects.front();
in_subq != in_subq_end &&
join->tables + (*in_subq)->unit->first_select()->join->tables < MAX_TABLES;
in_subq++)
{
Item **tree= ((*in_subq)->emb_on_expr_nest == (TABLE_LIST*)1)?
&join->conds : &((*in_subq)->emb_on_expr_nest->on_expr);
Item *replace_me= *in_subq;
/*
JTBM: the subquery was already mapped with Item_in_optimizer, so we
should search for that, not for original Item_in_subselect.
TODO: what about delaying that rewrite until here?
*/
if (!(*in_subq)->convert_to_semi_join)
{
replace_me= (*in_subq)->optimizer;
}
if (replace_where_subcondition(join, tree, replace_me, new Item_int(1),
FALSE))
DBUG_RETURN(TRUE); /* purecov: inspected */
}
#endif
for (in_subq= join->sj_subselects.front(); for (in_subq= join->sj_subselects.front();
in_subq != in_subq_end && in_subq != in_subq_end &&
...@@ -543,8 +524,6 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) ...@@ -543,8 +524,6 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
in_subq++) in_subq++)
{ {
bool remove_item= TRUE; bool remove_item= TRUE;
//psergey-jtbm: todo: here: check if we should convert to semi-join or
// to JTBM nest.
if ((*in_subq)->convert_to_semi_join) if ((*in_subq)->convert_to_semi_join)
{ {
if (convert_subq_to_sj(join, *in_subq)) if (convert_subq_to_sj(join, *in_subq))
...@@ -668,6 +647,7 @@ void get_temptable_params(Item_in_subselect *item, ha_rows *out_rows, ...@@ -668,6 +647,7 @@ void get_temptable_params(Item_in_subselect *item, ha_rows *out_rows,
*scan_time= data_size/IO_SIZE + 2; *scan_time= data_size/IO_SIZE + 2;
} }
/** /**
@brief Replaces an expression destructively inside the expression tree of @brief Replaces an expression destructively inside the expression tree of
the WHERE clase. the WHERE clase.
...@@ -685,6 +665,7 @@ void get_temptable_params(Item_in_subselect *item, ha_rows *out_rows, ...@@ -685,6 +665,7 @@ void get_temptable_params(Item_in_subselect *item, ha_rows *out_rows,
@return <code>true</code> if there was an error, <code>false</code> if @return <code>true</code> if there was an error, <code>false</code> if
successful. successful.
*/ */
static bool replace_where_subcondition(JOIN *join, Item **expr, static bool replace_where_subcondition(JOIN *join, Item **expr,
Item *old_cond, Item *new_cond, Item *old_cond, Item *new_cond,
bool do_fix_fields) bool do_fix_fields)
...@@ -920,8 +901,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) ...@@ -920,8 +901,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
/* 3. Remove the original subquery predicate from the WHERE/ON */ /* 3. Remove the original subquery predicate from the WHERE/ON */
// The subqueries were replaced for Item_int(1) earlier // The subqueries were replaced for Item_int(1) earlier
subq_pred->exec_method= subq_pred->exec_method= Item_in_subselect::SEMI_JOIN; // for subsequent executions
Item_in_subselect::SEMI_JOIN; // for subsequent executions
/*TODO: also reset the 'with_subselect' there. */ /*TODO: also reset the 'with_subselect' there. */
/* n. Adjust the parent_join->tables counter */ /* n. Adjust the parent_join->tables counter */
...@@ -1046,7 +1026,7 @@ static bool convert_subq_to_jtbm(JOIN *parent_join, ...@@ -1046,7 +1026,7 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
SELECT_LEX *parent_lex= parent_join->select_lex; SELECT_LEX *parent_lex= parent_join->select_lex;
List<TABLE_LIST> *emb_join_list= &parent_lex->top_join_list; List<TABLE_LIST> *emb_join_list= &parent_lex->top_join_list;
TABLE_LIST *emb_tbl_nest= NULL; // will change when we learn to handle outer joins TABLE_LIST *emb_tbl_nest= NULL; // will change when we learn to handle outer joins
TABLE_LIST *tl;//, *last_leaf; TABLE_LIST *tl;
DBUG_ENTER("convert_subq_to_jtbm"); DBUG_ENTER("convert_subq_to_jtbm");
if (subq_pred->setup_engine(TRUE)) if (subq_pred->setup_engine(TRUE))
...@@ -1071,7 +1051,6 @@ static bool convert_subq_to_jtbm(JOIN *parent_join, ...@@ -1071,7 +1051,6 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
jtbm->join_list= emb_join_list; jtbm->join_list= emb_join_list;
jtbm->embedding= emb_tbl_nest; jtbm->embedding= emb_tbl_nest;
jtbm->alias= (char*)"(jtbm)";
jtbm->jtbm_subselect= subq_pred; jtbm->jtbm_subselect= subq_pred;
jtbm->nested_join= NULL; jtbm->nested_join= NULL;
...@@ -1504,6 +1483,7 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map) ...@@ -1504,6 +1483,7 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
/* /*
Get estimated record length for semi-join materialization temptable Get estimated record length for semi-join materialization temptable
...@@ -1627,6 +1607,7 @@ bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables) ...@@ -1627,6 +1607,7 @@ bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables)
return FALSE; return FALSE;
} }
/* /*
Do semi-join optimization step after we've added a new tab to join prefix Do semi-join optimization step after we've added a new tab to join prefix
...@@ -3762,6 +3743,7 @@ static void remove_subq_pushed_predicates(JOIN *join, Item **where) ...@@ -3762,6 +3743,7 @@ static void remove_subq_pushed_predicates(JOIN *join, Item **where)
} }
} }
int do_jtbm_materialization_if_needed(JOIN_TAB *tab) int do_jtbm_materialization_if_needed(JOIN_TAB *tab)
{ {
Item_in_subselect *in_subs; Item_in_subselect *in_subs;
......
/* */ /*
Semi-join subquery optimization code definitions
*/
#ifdef USE_PRAGMA_INTERFACE #ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
...@@ -365,4 +367,8 @@ int clear_sj_tmp_tables(JOIN *join); ...@@ -365,4 +367,8 @@ int clear_sj_tmp_tables(JOIN *join);
int rewrite_to_index_subquery_engine(JOIN *join); int rewrite_to_index_subquery_engine(JOIN *join);
void get_temptable_params(Item_in_subselect *item, ha_rows *out_rows,
ha_rows *scan_time);
int do_jtbm_materialization_if_needed(JOIN_TAB *tab);
...@@ -243,10 +243,6 @@ join_read_record_no_init(JOIN_TAB *tab); ...@@ -243,10 +243,6 @@ join_read_record_no_init(JOIN_TAB *tab);
Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field, Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
bool *inherited_fl); bool *inherited_fl);
void get_temptable_params(Item_in_subselect *item, ha_rows *out_rows,
ha_rows *scan_time);
int do_jtbm_materialization_if_needed(JOIN_TAB *tab);
/** /**
This handles SELECT with and without UNION. This handles SELECT with and without UNION.
*/ */
...@@ -2634,7 +2630,6 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, ...@@ -2634,7 +2630,6 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
no_rows_const_tables |= table->map; no_rows_const_tables |= table->map;
} }
} }
//psergey-todo: inject jtbm JOIN_TABS here.
stat_vector[i]=0; stat_vector[i]=0;
join->outer_join=outer_join; join->outer_join=outer_join;
...@@ -7723,7 +7718,7 @@ void JOIN_TAB::cleanup() ...@@ -7723,7 +7718,7 @@ void JOIN_TAB::cleanup()
table->file->extra(HA_EXTRA_NO_KEYREAD); table->file->extra(HA_EXTRA_NO_KEYREAD);
} }
table->file->ha_index_or_rnd_end(); table->file->ha_index_or_rnd_end();
//psergey-jtbm2:
if (table->pos_in_table_list && if (table->pos_in_table_list &&
table->pos_in_table_list->jtbm_subselect) table->pos_in_table_list->jtbm_subselect)
{ {
...@@ -11570,7 +11565,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -11570,7 +11565,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
{ {
key_part_info->null_bit=0; key_part_info->null_bit=0;
key_part_info->field= *reg_field; key_part_info->field= *reg_field;
//psergey-jtbm:
(*reg_field)->flags |= PART_KEY_FLAG; (*reg_field)->flags |= PART_KEY_FLAG;
if (key_part_info == keyinfo->key_part) if (key_part_info == keyinfo->key_part)
(*reg_field)->key_start.set_bit(0); (*reg_field)->key_start.set_bit(0);
......
...@@ -1552,18 +1552,11 @@ class JOIN :public Sql_alloc ...@@ -1552,18 +1552,11 @@ class JOIN :public Sql_alloc
bool optimized; ///< flag to avoid double optimization in EXPLAIN bool optimized; ///< flag to avoid double optimization in EXPLAIN
/* /*
Subqueries that will need to be converted to semi-join nests (the list Subqueries that will need to be converted to semi-join nests, including
is emptied when conversion is done those converted to jtbm nests. The list is emptied when conversion is done.
*/ */
Array<Item_in_subselect> sj_subselects; Array<Item_in_subselect> sj_subselects;
/*
Subqueries that will need to be converted to JOIN_TABs
(Note this is different from the above in the respect that it's part
of WHERE clause or something like that?)
*/
//Array<Item_in_subselect> jtbm_subselects;
/* Temporary tables used to weed-out semi-join duplicates */ /* Temporary tables used to weed-out semi-join duplicates */
List<TABLE> sj_tmp_tables; List<TABLE> sj_tmp_tables;
List<SJ_MATERIALIZATION_INFO> sjm_info_list; List<SJ_MATERIALIZATION_INFO> sjm_info_list;
...@@ -1586,7 +1579,6 @@ class JOIN :public Sql_alloc ...@@ -1586,7 +1579,6 @@ class JOIN :public Sql_alloc
JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg, JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
select_result *result_arg) select_result *result_arg)
:fields_list(fields_arg), sj_subselects(thd_arg->mem_root, 4) :fields_list(fields_arg), sj_subselects(thd_arg->mem_root, 4)
//jtbm_subselects(thd_arg->mem_root, 4)
{ {
init(thd_arg, fields_arg, select_options_arg, result_arg); init(thd_arg, fields_arg, select_options_arg, result_arg);
} }
......
...@@ -1131,7 +1131,7 @@ class Item_in_subselect; ...@@ -1131,7 +1131,7 @@ class Item_in_subselect;
1) table (TABLE_LIST::view == NULL) 1) table (TABLE_LIST::view == NULL)
- base table - base table
(TABLE_LIST::derived == NULL) (TABLE_LIST::derived == NULL)
- subquery - TABLE_LIST::table is a temp table - FROM-clause subquery - TABLE_LIST::table is a temp table
(TABLE_LIST::derived != NULL) (TABLE_LIST::derived != NULL)
- information schema table - information schema table
(TABLE_LIST::schema_table != NULL) (TABLE_LIST::schema_table != NULL)
...@@ -1150,6 +1150,8 @@ class Item_in_subselect; ...@@ -1150,6 +1150,8 @@ class Item_in_subselect;
(TABLE_LIST::natural_join != NULL) (TABLE_LIST::natural_join != NULL)
- JOIN ... USING - JOIN ... USING
(TABLE_LIST::join_using_fields != NULL) (TABLE_LIST::join_using_fields != NULL)
- semi-join nest (sj_on_expr!= NULL && sj_subq_pred!=NULL)
4) jtbm semi-join (jtbm_subselect != NULL)
*/ */
class Index_hint; class Index_hint;
...@@ -1192,9 +1194,14 @@ struct TABLE_LIST ...@@ -1192,9 +1194,14 @@ struct TABLE_LIST
*/ */
table_map sj_inner_tables; table_map sj_inner_tables;
/* Number of IN-compared expressions */ /* Number of IN-compared expressions */
uint sj_in_exprs; uint sj_in_exprs;
/* If this is a non-jtbm semi-join nest: corresponding subselect predicate */
Item_in_subselect *sj_subq_pred; Item_in_subselect *sj_subq_pred;
/* If this is a jtbm semi-join object: corresponding subselect predicate */
Item_in_subselect *jtbm_subselect; Item_in_subselect *jtbm_subselect;
SJ_MATERIALIZATION_INFO *sj_mat_info; SJ_MATERIALIZATION_INFO *sj_mat_info;
/* /*
......
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