MWL#90: Address review feedback part #5
This commit is contained in:
parent
809a805251
commit
b77e3dc9f4
@ -33,11 +33,11 @@
|
|||||||
|
|
||||||
|
|
||||||
Item_subselect::Item_subselect():
|
Item_subselect::Item_subselect():
|
||||||
Item_result_field(), value_assigned(0), thd(0), substitution(0),
|
Item_result_field(), value_assigned(0), thd(0), old_engine(0),
|
||||||
expr_cache(0), engine(0), old_engine(0), used_tables_cache(0),
|
used_tables_cache(0), have_to_be_excluded(0), const_item_cache(1),
|
||||||
have_to_be_excluded(0), const_item_cache(1), inside_first_fix_fields(0),
|
inside_first_fix_fields(0), done_first_fix_fields(FALSE),
|
||||||
done_first_fix_fields(FALSE), eliminated(FALSE), engine_changed(0),
|
substitution(0), expr_cache(0), engine(0), eliminated(FALSE),
|
||||||
changed(0), is_correlated(FALSE)
|
engine_changed(0), changed(0), is_correlated(FALSE)
|
||||||
{
|
{
|
||||||
with_subselect= 1;
|
with_subselect= 1;
|
||||||
reset();
|
reset();
|
||||||
|
@ -36,27 +36,6 @@ class Item_subselect :public Item_result_field
|
|||||||
protected:
|
protected:
|
||||||
/* thread handler, will be assigned in fix_fields only */
|
/* thread handler, will be assigned in fix_fields only */
|
||||||
THD *thd;
|
THD *thd;
|
||||||
/*
|
|
||||||
Used inside Item_subselect::fix_fields() according to this scenario:
|
|
||||||
> Item_subselect::fix_fields
|
|
||||||
> engine->prepare
|
|
||||||
> child_join->prepare
|
|
||||||
(Here we realize we need to do the rewrite and set
|
|
||||||
substitution= some new Item, eg. Item_in_optimizer )
|
|
||||||
< child_join->prepare
|
|
||||||
< engine->prepare
|
|
||||||
*ref= substitution;
|
|
||||||
substitution= NULL;
|
|
||||||
< Item_subselect::fix_fields
|
|
||||||
*/
|
|
||||||
public:
|
|
||||||
Item *substitution;
|
|
||||||
/* unit of subquery */
|
|
||||||
st_select_lex_unit *unit;
|
|
||||||
Item *expr_cache;
|
|
||||||
/* engine that perform execution of subselect (single select or union) */
|
|
||||||
subselect_engine *engine;
|
|
||||||
protected:
|
|
||||||
/* old engine if engine was changed */
|
/* old engine if engine was changed */
|
||||||
subselect_engine *old_engine;
|
subselect_engine *old_engine;
|
||||||
/* cache of used external tables */
|
/* cache of used external tables */
|
||||||
@ -73,6 +52,25 @@ protected:
|
|||||||
bool inside_first_fix_fields;
|
bool inside_first_fix_fields;
|
||||||
bool done_first_fix_fields;
|
bool done_first_fix_fields;
|
||||||
public:
|
public:
|
||||||
|
/*
|
||||||
|
Used inside Item_subselect::fix_fields() according to this scenario:
|
||||||
|
> Item_subselect::fix_fields
|
||||||
|
> engine->prepare
|
||||||
|
> child_join->prepare
|
||||||
|
(Here we realize we need to do the rewrite and set
|
||||||
|
substitution= some new Item, eg. Item_in_optimizer )
|
||||||
|
< child_join->prepare
|
||||||
|
< engine->prepare
|
||||||
|
*ref= substitution;
|
||||||
|
substitution= NULL;
|
||||||
|
< Item_subselect::fix_fields
|
||||||
|
*/
|
||||||
|
Item *substitution;
|
||||||
|
/* unit of subquery */
|
||||||
|
st_select_lex_unit *unit;
|
||||||
|
Item *expr_cache;
|
||||||
|
/* engine that perform execution of subselect (single select or union) */
|
||||||
|
subselect_engine *engine;
|
||||||
/* A reference from inside subquery predicate to somewhere outside of it */
|
/* A reference from inside subquery predicate to somewhere outside of it */
|
||||||
class Ref_to_outside : public Sql_alloc
|
class Ref_to_outside : public Sql_alloc
|
||||||
{
|
{
|
||||||
@ -774,61 +772,26 @@ public:
|
|||||||
of subselect_single_select_engine::[prepare | cols].
|
of subselect_single_select_engine::[prepare | cols].
|
||||||
*/
|
*/
|
||||||
subselect_single_select_engine *materialize_engine;
|
subselect_single_select_engine *materialize_engine;
|
||||||
protected:
|
|
||||||
/* The engine used to compute the IN predicate. */
|
|
||||||
subselect_engine *lookup_engine;
|
|
||||||
/*
|
/*
|
||||||
QEP to execute the subquery and materialize its result into a
|
QEP to execute the subquery and materialize its result into a
|
||||||
temporary table. Created during the first call to exec().
|
temporary table. Created during the first call to exec().
|
||||||
*/
|
*/
|
||||||
public:
|
|
||||||
JOIN *materialize_join;
|
JOIN *materialize_join;
|
||||||
protected:
|
|
||||||
/* Keyparts of the only non-NULL composite index in a rowid merge. */
|
|
||||||
MY_BITMAP non_null_key_parts;
|
|
||||||
/* Keyparts of the single column indexes with NULL, one keypart per index. */
|
|
||||||
MY_BITMAP partial_match_key_parts;
|
|
||||||
uint count_partial_match_columns;
|
|
||||||
uint count_null_only_columns;
|
|
||||||
/*
|
/*
|
||||||
A conjunction of all the equality condtions between all pairs of expressions
|
A conjunction of all the equality condtions between all pairs of expressions
|
||||||
that are arguments of an IN predicate. We need these to post-filter some
|
that are arguments of an IN predicate. We need these to post-filter some
|
||||||
IN results because index lookups sometimes match values that are actually
|
IN results because index lookups sometimes match values that are actually
|
||||||
not equal to the search key in SQL terms.
|
not equal to the search key in SQL terms.
|
||||||
*/
|
*/
|
||||||
public:
|
|
||||||
Item_cond_and *semi_join_conds;
|
Item_cond_and *semi_join_conds;
|
||||||
protected:
|
|
||||||
/* Possible execution strategies that can be used to compute hash semi-join.*/
|
|
||||||
enum exec_strategy {
|
|
||||||
UNDEFINED,
|
|
||||||
COMPLETE_MATCH, /* Use regular index lookups. */
|
|
||||||
PARTIAL_MATCH, /* Use some partial matching strategy. */
|
|
||||||
PARTIAL_MATCH_MERGE, /* Use partial matching through index merging. */
|
|
||||||
PARTIAL_MATCH_SCAN, /* Use partial matching through table scan. */
|
|
||||||
IMPOSSIBLE /* Subquery materialization is not applicable. */
|
|
||||||
};
|
|
||||||
/* The chosen execution strategy. Computed after materialization. */
|
|
||||||
exec_strategy strategy;
|
|
||||||
protected:
|
|
||||||
exec_strategy get_strategy_using_schema();
|
|
||||||
exec_strategy get_strategy_using_data();
|
|
||||||
ulonglong rowid_merge_buff_size(bool has_non_null_key,
|
|
||||||
bool has_covering_null_row,
|
|
||||||
MY_BITMAP *partial_match_key_parts);
|
|
||||||
void choose_partial_match_strategy(bool has_non_null_key,
|
|
||||||
bool has_covering_null_row,
|
|
||||||
MY_BITMAP *partial_match_key_parts);
|
|
||||||
bool make_semi_join_conds();
|
|
||||||
subselect_uniquesubquery_engine* make_unique_engine();
|
|
||||||
|
|
||||||
public:
|
|
||||||
subselect_hash_sj_engine(THD *thd, Item_subselect *in_predicate,
|
subselect_hash_sj_engine(THD *thd, Item_subselect *in_predicate,
|
||||||
subselect_single_select_engine *old_engine)
|
subselect_single_select_engine *old_engine)
|
||||||
:subselect_engine(thd, in_predicate, NULL), tmp_table(NULL),
|
: subselect_engine(thd, in_predicate, NULL),
|
||||||
is_materialized(FALSE), materialize_engine(old_engine), lookup_engine(NULL),
|
tmp_table(NULL), is_materialized(FALSE), materialize_engine(old_engine),
|
||||||
materialize_join(NULL), count_partial_match_columns(0),
|
materialize_join(NULL), semi_join_conds(NULL), lookup_engine(NULL),
|
||||||
count_null_only_columns(0), semi_join_conds(NULL), strategy(UNDEFINED)
|
count_partial_match_columns(0), count_null_only_columns(0),
|
||||||
|
strategy(UNDEFINED)
|
||||||
{}
|
{}
|
||||||
~subselect_hash_sj_engine();
|
~subselect_hash_sj_engine();
|
||||||
|
|
||||||
@ -856,6 +819,38 @@ public:
|
|||||||
//=>base class
|
//=>base class
|
||||||
bool change_result(Item_subselect *si, select_result_interceptor *result);
|
bool change_result(Item_subselect *si, select_result_interceptor *result);
|
||||||
bool no_tables();//=>base class
|
bool no_tables();//=>base class
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* The engine used to compute the IN predicate. */
|
||||||
|
subselect_engine *lookup_engine;
|
||||||
|
/* Keyparts of the only non-NULL composite index in a rowid merge. */
|
||||||
|
MY_BITMAP non_null_key_parts;
|
||||||
|
/* Keyparts of the single column indexes with NULL, one keypart per index. */
|
||||||
|
MY_BITMAP partial_match_key_parts;
|
||||||
|
uint count_partial_match_columns;
|
||||||
|
uint count_null_only_columns;
|
||||||
|
/* Possible execution strategies that can be used to compute hash semi-join.*/
|
||||||
|
enum exec_strategy {
|
||||||
|
UNDEFINED,
|
||||||
|
COMPLETE_MATCH, /* Use regular index lookups. */
|
||||||
|
PARTIAL_MATCH, /* Use some partial matching strategy. */
|
||||||
|
PARTIAL_MATCH_MERGE, /* Use partial matching through index merging. */
|
||||||
|
PARTIAL_MATCH_SCAN, /* Use partial matching through table scan. */
|
||||||
|
IMPOSSIBLE /* Subquery materialization is not applicable. */
|
||||||
|
};
|
||||||
|
/* The chosen execution strategy. Computed after materialization. */
|
||||||
|
exec_strategy strategy;
|
||||||
|
exec_strategy get_strategy_using_schema();
|
||||||
|
exec_strategy get_strategy_using_data();
|
||||||
|
ulonglong rowid_merge_buff_size(bool has_non_null_key,
|
||||||
|
bool has_covering_null_row,
|
||||||
|
MY_BITMAP *partial_match_key_parts);
|
||||||
|
void choose_partial_match_strategy(bool has_non_null_key,
|
||||||
|
bool has_covering_null_row,
|
||||||
|
MY_BITMAP *partial_match_key_parts);
|
||||||
|
bool make_semi_join_conds();
|
||||||
|
subselect_uniquesubquery_engine* make_unique_engine();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -826,15 +826,12 @@ void get_delayed_table_estimates(TABLE *table,
|
|||||||
((subselect_hash_sj_engine*)item->engine);
|
((subselect_hash_sj_engine*)item->engine);
|
||||||
JOIN *join= hash_sj_engine->materialize_join;
|
JOIN *join= hash_sj_engine->materialize_join;
|
||||||
|
|
||||||
double rows= 1;
|
double rows;
|
||||||
double read_time= 0.0;
|
double read_time;
|
||||||
|
|
||||||
/* Calculate #rows and cost of join execution */
|
/* Calculate #rows and cost of join execution */
|
||||||
for (uint i= join->const_tables; i < join->tables; i++)
|
get_partial_join_cost(join, join->tables, &read_time, &rows);
|
||||||
{
|
|
||||||
rows *= join->best_positions[i].records_read;
|
|
||||||
read_time += join->best_positions[i].read_time;
|
|
||||||
}
|
|
||||||
*out_rows= (ha_rows)rows;
|
*out_rows= (ha_rows)rows;
|
||||||
*startup_cost= read_time;
|
*startup_cost= read_time;
|
||||||
/* Calculate cost of scanning the temptable */
|
/* Calculate cost of scanning the temptable */
|
||||||
|
@ -185,6 +185,7 @@ void JOIN_CACHE::calc_record_fields()
|
|||||||
start_tab= tab;
|
start_tab= tab;
|
||||||
if (start_tab->bush_children)
|
if (start_tab->bush_children)
|
||||||
start_tab= start_tab->bush_children->start;
|
start_tab= start_tab->bush_children->start;
|
||||||
|
DBUG_ASSERT(!start_tab->bush_children);
|
||||||
|
|
||||||
tab= start_tab;
|
tab= start_tab;
|
||||||
|
|
||||||
@ -508,7 +509,6 @@ void JOIN_CACHE::create_key_arg_fields()
|
|||||||
/* Now create local fields that are used to build ref for this key access */
|
/* Now create local fields that are used to build ref for this key access */
|
||||||
copy= field_descr+flag_fields;
|
copy= field_descr+flag_fields;
|
||||||
for (tab= start_tab; tab != join_tab; tab= next_linear_tab(join, tab, FALSE))
|
for (tab= start_tab; tab != join_tab; tab= next_linear_tab(join, tab, FALSE))
|
||||||
//for (tab= join_tab-tables; tab; tab= get_next_table(tab))
|
|
||||||
{
|
{
|
||||||
length+= add_table_data_fields_to_join_cache(tab, &tab->table->tmp_set,
|
length+= add_table_data_fields_to_join_cache(tab, &tab->table->tmp_set,
|
||||||
&data_field_count, ©,
|
&data_field_count, ©,
|
||||||
@ -721,8 +721,11 @@ ulong JOIN_CACHE::get_min_join_buffer_size()
|
|||||||
if (!min_buff_size)
|
if (!min_buff_size)
|
||||||
{
|
{
|
||||||
size_t len= 0;
|
size_t len= 0;
|
||||||
for (JOIN_TAB *tab= start_tab; tab != join_tab; tab= next_linear_tab(join, tab, FALSE))
|
for (JOIN_TAB *tab= start_tab; tab != join_tab;
|
||||||
|
tab= next_linear_tab(join, tab, FALSE))
|
||||||
|
{
|
||||||
len+= tab->get_max_used_fieldlength();
|
len+= tab->get_max_used_fieldlength();
|
||||||
|
}
|
||||||
len+= get_record_max_affix_length() + get_max_key_addon_space_per_record();
|
len+= get_record_max_affix_length() + get_max_key_addon_space_per_record();
|
||||||
size_t min_sz= len*min_records;
|
size_t min_sz= len*min_records;
|
||||||
size_t add_sz= 0;
|
size_t add_sz= 0;
|
||||||
@ -774,8 +777,11 @@ ulong JOIN_CACHE::get_max_join_buffer_size(bool optimize_buff_size)
|
|||||||
size_t max_sz;
|
size_t max_sz;
|
||||||
size_t min_sz= get_min_join_buffer_size();
|
size_t min_sz= get_min_join_buffer_size();
|
||||||
size_t len= 0;
|
size_t len= 0;
|
||||||
for (JOIN_TAB *tab= start_tab; tab != join_tab; tab= next_linear_tab(join, tab, FALSE))
|
for (JOIN_TAB *tab= start_tab; tab != join_tab;
|
||||||
|
tab= next_linear_tab(join, tab, FALSE))
|
||||||
|
{
|
||||||
len+= tab->get_used_fieldlength();
|
len+= tab->get_used_fieldlength();
|
||||||
|
}
|
||||||
len+= get_record_max_affix_length();
|
len+= get_record_max_affix_length();
|
||||||
avg_record_length= len;
|
avg_record_length= len;
|
||||||
len+= get_max_key_addon_space_per_record() + avg_aux_buffer_incr;
|
len+= get_max_key_addon_space_per_record() + avg_aux_buffer_incr;
|
||||||
|
@ -1035,16 +1035,8 @@ JOIN::optimize()
|
|||||||
Perform the optimization on fields evaluation mentioned above
|
Perform the optimization on fields evaluation mentioned above
|
||||||
for all on expressions.
|
for all on expressions.
|
||||||
*/
|
*/
|
||||||
|
for (JOIN_TAB *tab= first_linear_tab(this, TRUE); tab;
|
||||||
{
|
tab= next_linear_tab(this, tab, TRUE))
|
||||||
List_iterator<JOIN_TAB_RANGE> it(join_tab_ranges);
|
|
||||||
JOIN_TAB_RANGE *jt_range;
|
|
||||||
/* For upper level JOIN_TABs, we need to skip the const tables: */
|
|
||||||
uint first_tab_offs= const_tables;
|
|
||||||
while ((jt_range= it++))
|
|
||||||
{
|
|
||||||
for (JOIN_TAB *tab= jt_range->start + first_tab_offs;
|
|
||||||
tab < jt_range->end; tab++)
|
|
||||||
{
|
{
|
||||||
if (*tab->on_expr_ref)
|
if (*tab->on_expr_ref)
|
||||||
{
|
{
|
||||||
@ -1054,34 +1046,17 @@ JOIN::optimize()
|
|||||||
(*tab->on_expr_ref)->update_used_tables();
|
(*tab->on_expr_ref)->update_used_tables();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Next jt_range will refer to SJM nest (and not the top-level range).
|
|
||||||
Inside SJM nests, we dont have const tables, so should start from the
|
|
||||||
first table:
|
|
||||||
*/
|
|
||||||
first_tab_offs= 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Perform the optimization on fields evaliation mentioned above
|
Perform the optimization on fields evaliation mentioned above
|
||||||
for all used ref items.
|
for all used ref items.
|
||||||
*/
|
*/
|
||||||
//for (JOIN_TAB *tab= join_tab + const_tables; tab < join_tab + tables; tab++)
|
for (JOIN_TAB *tab= first_linear_tab(this, TRUE); tab;
|
||||||
//{
|
tab= next_linear_tab(this, tab, TRUE))
|
||||||
{
|
|
||||||
List_iterator<JOIN_TAB_RANGE> it(join_tab_ranges);
|
|
||||||
JOIN_TAB_RANGE *jt_range;
|
|
||||||
uint first_tab_offs= const_tables;
|
|
||||||
while ((jt_range= it++))
|
|
||||||
{
|
|
||||||
for (JOIN_TAB *tab= jt_range->start + first_tab_offs;
|
|
||||||
tab < jt_range->end; tab++)
|
|
||||||
{
|
{
|
||||||
uint key_copy_index=0;
|
uint key_copy_index=0;
|
||||||
for (uint i=0; i < tab->ref.key_parts; i++)
|
for (uint i=0; i < tab->ref.key_parts; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
Item **ref_item_ptr= tab->ref.items+i;
|
Item **ref_item_ptr= tab->ref.items+i;
|
||||||
Item *ref_item= *ref_item_ptr;
|
Item *ref_item= *ref_item_ptr;
|
||||||
if (!ref_item->used_tables() && !(select_options & SELECT_DESCRIBE))
|
if (!ref_item->used_tables() && !(select_options & SELECT_DESCRIBE))
|
||||||
@ -1104,10 +1079,6 @@ JOIN::optimize()
|
|||||||
key_copy_index++;
|
key_copy_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
first_tab_offs= 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (conds && const_table_map != found_const_table_map &&
|
if (conds && const_table_map != found_const_table_map &&
|
||||||
(select_options & SELECT_DESCRIBE))
|
(select_options & SELECT_DESCRIBE))
|
||||||
@ -1638,9 +1609,6 @@ bool JOIN::setup_subquery_caches()
|
|||||||
for (JOIN_TAB *tab= first_linear_tab(this, TRUE);
|
for (JOIN_TAB *tab= first_linear_tab(this, TRUE);
|
||||||
tab;
|
tab;
|
||||||
tab= next_linear_tab(this, tab, TRUE))
|
tab= next_linear_tab(this, tab, TRUE))
|
||||||
//for (JOIN_TAB *tab= join_tab + const_tables;
|
|
||||||
// tab < join_tab + tables ;
|
|
||||||
// tab++)
|
|
||||||
{
|
{
|
||||||
if (tab->select_cond)
|
if (tab->select_cond)
|
||||||
tab->select_cond=
|
tab->select_cond=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user