diff options
-rw-r--r-- | sql/item_subselect.cc | 10 | ||||
-rw-r--r-- | sql/item_subselect.h | 113 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 11 | ||||
-rw-r--r-- | sql/sql_join_cache.cc | 12 | ||||
-rw-r--r-- | sql/sql_select.cc | 84 |
5 files changed, 98 insertions, 132 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 324a331c32b..283a96d6149 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -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(); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 39780708e60..b3b4c717f38 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -36,6 +36,22 @@ class Item_subselect :public Item_result_field protected: /* thread handler, will be assigned in fix_fields only */ THD *thd; + /* old engine if engine was changed */ + subselect_engine *old_engine; + /* cache of used external tables */ + table_map used_tables_cache; + /* allowed number of columns (1 for single value subqueries) */ + uint max_columns; + /* where subquery is placed */ + enum_parsing_place parsing_place; + /* work with 'substitution' */ + bool have_to_be_excluded; + /* cache of constant state */ + bool const_item_cache; + + 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 @@ -49,30 +65,12 @@ protected: 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 */ - table_map used_tables_cache; - /* allowed number of columns (1 for single value subqueries) */ - uint max_columns; - /* where subquery is placed */ - enum_parsing_place parsing_place; - /* work with 'substitution' */ - bool have_to_be_excluded; - /* cache of constant state */ - bool const_item_cache; - - bool inside_first_fix_fields; - bool done_first_fix_fields; -public: /* 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(); + }; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index a4d5578f3cf..2601e54b865 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -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 */ diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index face1f9196e..af0c3c6709e 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -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; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d443fbc802d..b5d6cc1acb6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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= |