mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
MWL#90: Address review feedback part #5
This commit is contained in:
parent
809a805251
commit
b77e3dc9f4
5 changed files with 101 additions and 135 deletions
|
@ -33,11 +33,11 @@
|
|||
|
||||
|
||||
Item_subselect::Item_subselect():
|
||||
Item_result_field(), value_assigned(0), thd(0), substitution(0),
|
||||
expr_cache(0), engine(0), old_engine(0), used_tables_cache(0),
|
||||
have_to_be_excluded(0), const_item_cache(1), inside_first_fix_fields(0),
|
||||
done_first_fix_fields(FALSE), eliminated(FALSE), engine_changed(0),
|
||||
changed(0), is_correlated(FALSE)
|
||||
Item_result_field(), value_assigned(0), thd(0), old_engine(0),
|
||||
used_tables_cache(0), have_to_be_excluded(0), const_item_cache(1),
|
||||
inside_first_fix_fields(0), done_first_fix_fields(FALSE),
|
||||
substitution(0), expr_cache(0), engine(0), eliminated(FALSE),
|
||||
engine_changed(0), changed(0), is_correlated(FALSE)
|
||||
{
|
||||
with_subselect= 1;
|
||||
reset();
|
||||
|
|
|
@ -36,27 +36,6 @@ class Item_subselect :public Item_result_field
|
|||
protected:
|
||||
/* thread handler, will be assigned in fix_fields only */
|
||||
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 */
|
||||
subselect_engine *old_engine;
|
||||
/* cache of used external tables */
|
||||
|
@ -73,6 +52,25 @@ protected:
|
|||
bool inside_first_fix_fields;
|
||||
bool done_first_fix_fields;
|
||||
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 */
|
||||
class Ref_to_outside : public Sql_alloc
|
||||
{
|
||||
|
@ -774,61 +772,26 @@ public:
|
|||
of subselect_single_select_engine::[prepare | cols].
|
||||
*/
|
||||
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
|
||||
temporary table. Created during the first call to exec().
|
||||
*/
|
||||
public:
|
||||
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
|
||||
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
|
||||
not equal to the search key in SQL terms.
|
||||
*/
|
||||
public:
|
||||
*/
|
||||
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_single_select_engine *old_engine)
|
||||
:subselect_engine(thd, in_predicate, NULL), tmp_table(NULL),
|
||||
is_materialized(FALSE), materialize_engine(old_engine), lookup_engine(NULL),
|
||||
materialize_join(NULL), count_partial_match_columns(0),
|
||||
count_null_only_columns(0), semi_join_conds(NULL), strategy(UNDEFINED)
|
||||
: subselect_engine(thd, in_predicate, NULL),
|
||||
tmp_table(NULL), is_materialized(FALSE), materialize_engine(old_engine),
|
||||
materialize_join(NULL), semi_join_conds(NULL), lookup_engine(NULL),
|
||||
count_partial_match_columns(0), count_null_only_columns(0),
|
||||
strategy(UNDEFINED)
|
||||
{}
|
||||
~subselect_hash_sj_engine();
|
||||
|
||||
|
@ -856,6 +819,38 @@ public:
|
|||
//=>base class
|
||||
bool change_result(Item_subselect *si, select_result_interceptor *result);
|
||||
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);
|
||||
JOIN *join= hash_sj_engine->materialize_join;
|
||||
|
||||
double rows= 1;
|
||||
double read_time= 0.0;
|
||||
double rows;
|
||||
double read_time;
|
||||
|
||||
/* Calculate #rows and cost of join execution */
|
||||
for (uint i= join->const_tables; i < join->tables; i++)
|
||||
{
|
||||
rows *= join->best_positions[i].records_read;
|
||||
read_time += join->best_positions[i].read_time;
|
||||
}
|
||||
get_partial_join_cost(join, join->tables, &read_time, &rows);
|
||||
|
||||
*out_rows= (ha_rows)rows;
|
||||
*startup_cost= read_time;
|
||||
/* Calculate cost of scanning the temptable */
|
||||
|
|
|
@ -185,6 +185,7 @@ void JOIN_CACHE::calc_record_fields()
|
|||
start_tab= tab;
|
||||
if (start_tab->bush_children)
|
||||
start_tab= start_tab->bush_children->start;
|
||||
DBUG_ASSERT(!start_tab->bush_children);
|
||||
|
||||
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 */
|
||||
copy= field_descr+flag_fields;
|
||||
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,
|
||||
&data_field_count, ©,
|
||||
|
@ -721,8 +721,11 @@ ulong JOIN_CACHE::get_min_join_buffer_size()
|
|||
if (!min_buff_size)
|
||||
{
|
||||
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+= get_record_max_affix_length() + get_max_key_addon_space_per_record();
|
||||
size_t min_sz= len*min_records;
|
||||
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 min_sz= get_min_join_buffer_size();
|
||||
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+= get_record_max_affix_length();
|
||||
avg_record_length= len;
|
||||
len+= get_max_key_addon_space_per_record() + avg_aux_buffer_incr;
|
||||
|
|
|
@ -1035,31 +1035,15 @@ JOIN::optimize()
|
|||
Perform the optimization on fields evaluation mentioned above
|
||||
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++))
|
||||
if (*tab->on_expr_ref)
|
||||
{
|
||||
for (JOIN_TAB *tab= jt_range->start + first_tab_offs;
|
||||
tab < jt_range->end; tab++)
|
||||
{
|
||||
if (*tab->on_expr_ref)
|
||||
{
|
||||
*tab->on_expr_ref= substitute_for_best_equal_field(*tab->on_expr_ref,
|
||||
tab->cond_equal,
|
||||
map2table);
|
||||
(*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;
|
||||
*tab->on_expr_ref= substitute_for_best_equal_field(*tab->on_expr_ref,
|
||||
tab->cond_equal,
|
||||
map2table);
|
||||
(*tab->on_expr_ref)->update_used_tables();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1067,47 +1051,34 @@ JOIN::optimize()
|
|||
Perform the optimization on fields evaliation mentioned above
|
||||
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;
|
||||
for (uint i=0; i < tab->ref.key_parts; i++)
|
||||
{
|
||||
|
||||
Item **ref_item_ptr= tab->ref.items+i;
|
||||
Item *ref_item= *ref_item_ptr;
|
||||
for (uint i=0; i < tab->ref.key_parts; i++)
|
||||
{
|
||||
Item **ref_item_ptr= tab->ref.items+i;
|
||||
Item *ref_item= *ref_item_ptr;
|
||||
if (!ref_item->used_tables() && !(select_options & SELECT_DESCRIBE))
|
||||
continue;
|
||||
COND_EQUAL *equals= tab->first_inner ? tab->first_inner->cond_equal :
|
||||
cond_equal;
|
||||
ref_item= substitute_for_best_equal_field(ref_item, equals, map2table);
|
||||
ref_item->update_used_tables();
|
||||
if (*ref_item_ptr != ref_item)
|
||||
{
|
||||
*ref_item_ptr= ref_item;
|
||||
Item *item= ref_item->real_item();
|
||||
COND_EQUAL *equals= tab->first_inner ? tab->first_inner->cond_equal :
|
||||
cond_equal;
|
||||
ref_item= substitute_for_best_equal_field(ref_item, equals, map2table);
|
||||
ref_item->update_used_tables();
|
||||
if (*ref_item_ptr != ref_item)
|
||||
{
|
||||
*ref_item_ptr= ref_item;
|
||||
Item *item= ref_item->real_item();
|
||||
store_key *key_copy= tab->ref.key_copy[key_copy_index];
|
||||
if (key_copy->type() == store_key::FIELD_STORE_KEY)
|
||||
{
|
||||
store_key_field *field_copy= ((store_key_field *)key_copy);
|
||||
field_copy->change_source_field((Item_field *) item);
|
||||
}
|
||||
}
|
||||
key_copy_index++;
|
||||
if (key_copy->type() == store_key::FIELD_STORE_KEY)
|
||||
{
|
||||
store_key_field *field_copy= ((store_key_field *)key_copy);
|
||||
field_copy->change_source_field((Item_field *) item);
|
||||
}
|
||||
}
|
||||
first_tab_offs= 0;
|
||||
key_copy_index++;
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
if (conds && const_table_map != found_const_table_map &&
|
||||
(select_options & SELECT_DESCRIBE))
|
||||
|
@ -1638,9 +1609,6 @@ bool JOIN::setup_subquery_caches()
|
|||
for (JOIN_TAB *tab= first_linear_tab(this, TRUE);
|
||||
tab;
|
||||
tab= next_linear_tab(this, tab, TRUE))
|
||||
//for (JOIN_TAB *tab= join_tab + const_tables;
|
||||
// tab < join_tab + tables ;
|
||||
// tab++)
|
||||
{
|
||||
if (tab->select_cond)
|
||||
tab->select_cond=
|
||||
|
|
Loading…
Add table
Reference in a new issue