diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-07-01 18:15:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-07-01 18:15:00 +0000 |
commit | a2a2e32c02643a0cec111511220227703fda1cd5 (patch) | |
tree | 69cc2b631234c2a8e026b9cd4d72676c61c594df /sql/opt_split.cc | |
parent | Releasing progress-linux version 1:10.11.8-1~progress7.99u1. (diff) | |
download | mariadb-a2a2e32c02643a0cec111511220227703fda1cd5.tar.xz mariadb-a2a2e32c02643a0cec111511220227703fda1cd5.zip |
Merging upstream version 1:11.4.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sql/opt_split.cc')
-rw-r--r-- | sql/opt_split.cc | 139 |
1 files changed, 82 insertions, 57 deletions
diff --git a/sql/opt_split.cc b/sql/opt_split.cc index 8e2b7e12..9ae3eb47 100644 --- a/sql/opt_split.cc +++ b/sql/opt_split.cc @@ -229,6 +229,7 @@ #include "mariadb.h" #include "sql_select.h" #include "opt_trace.h" +#include "optimizer_defaults.h" /* Info on a splitting field */ struct SplM_field_info @@ -286,10 +287,10 @@ public: List<SplM_plan_info> plan_cache; /* Cost of best execution plan for join when nothing is pushed */ double unsplit_cost; + /* Split operation cost (result form spl_postjoin_oper_cost()) */ + double unsplit_oper_cost; /* Cardinality of T when nothing is pushed */ double unsplit_card; - /* Lastly evaluated execution plan for 'join' with pushed equalities */ - SplM_plan_info *last_plan; double last_refills; SplM_plan_info *find_plan(TABLE *table, uint key, uint parts); @@ -665,7 +666,7 @@ add_ext_keyuse_for_splitting(Dynamic_array<KEYUSE_EXT> *ext_keyuses, keyuse_ext.sj_pred_no= added_key_field->sj_pred_no; keyuse_ext.validity_ref= 0; keyuse_ext.needed_in_prefix= added_key_field->val->used_tables() & - ~(OUTER_REF_TABLE_BIT | RAND_TABLE_BIT); + ~(OUTER_REF_TABLE_BIT | RAND_TABLE_BIT); keyuse_ext.validity_var= false; return ext_keyuses->push(keyuse_ext); } @@ -724,20 +725,28 @@ add_ext_keyuses_for_splitting_field(Dynamic_array<KEYUSE_EXT> *ext_keyuses, /* @brief Cost of the post join operation used in specification of splittable table + This does not include the cost of creating the temporary table as this + operation can be executed many times for the same temporary table. */ static double spl_postjoin_oper_cost(THD *thd, double join_record_count, uint rec_len) { double cost; - cost= get_tmp_table_write_cost(thd, join_record_count,rec_len) * - join_record_count; // cost to fill tmp table - cost+= get_tmp_table_lookup_cost(thd, join_record_count,rec_len) * - join_record_count; // cost to perform post join operation used here - cost+= get_tmp_table_lookup_cost(thd, join_record_count, rec_len) + - (join_record_count == 0 ? 0 : - join_record_count * log2 (join_record_count)) * - SORT_INDEX_CMP_COST; // cost to perform sorting + TMPTABLE_COSTS tmp_cost= get_tmp_table_costs(thd, join_record_count, + rec_len, 0, 1); + /* cost to fill tmp table */ + cost= tmp_cost.write * join_record_count; + /* cost to perform post join operation used here */ + cost+= tmp_cost.lookup * join_record_count; + /* cost to preform sorting */ + /* QQQ + We should use cost_of_filesort() for computing sort. + Do we always preform sorting ? If not, this should be done conditionally + */ + cost+= ((join_record_count == 0 ? 0 : + join_record_count * log2 (join_record_count)) * + SORT_INDEX_CMP_COST); return cost; } @@ -769,7 +778,6 @@ void JOIN::add_keyuses_for_splitting() size_t idx; KEYUSE_EXT *keyuse_ext; KEYUSE_EXT keyuse_ext_end; - double oper_cost; uint rec_len; uint added_keyuse_count; TABLE *table= select_lex->master_unit()->derived->table; @@ -792,14 +800,20 @@ void JOIN::add_keyuses_for_splitting() if (ext_keyuses_for_splitting->push(keyuse_ext_end)) goto err; // psergey-todo: trace anything here? - spl_opt_info->unsplit_card= join_record_count; + /* + Use the number of rows that was computed by + TABLE_LIST::fetch_number_of_rows(): + */ + spl_opt_info->unsplit_card= + rows2double(select_lex->master_unit()->derived->table->stat_records()); rec_len= table->s->rec_buff_length; - oper_cost= spl_postjoin_oper_cost(thd, join_record_count, rec_len); - - spl_opt_info->unsplit_cost= best_positions[table_count-1].read_time + - oper_cost; + spl_opt_info->unsplit_oper_cost= spl_postjoin_oper_cost(thd, + join_record_count, + rec_len); + spl_opt_info->unsplit_cost= (best_positions[table_count-1].read_time + + spl_opt_info->unsplit_oper_cost); if (!(save_qep= new Join_plan_state(table_count + 1))) goto err; @@ -963,6 +977,7 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(uint idx, uint best_key= 0; uint best_key_parts= 0; table_map best_param_tables= 0L; + bool chosen, already_printed; Json_writer_object trace_obj(thd, "choose_best_splitting"); Json_writer_array trace_arr(thd, "considered_keys"); /* @@ -1033,8 +1048,8 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(uint idx, while (keyuse_ext->table == table); } trace_arr.end(); + chosen= 0; - spl_opt_info->last_plan= 0; double refills= DBL_MAX; table_map excluded_tables= remaining_tables | this->join->sjm_lookup_tables; if (best_table) @@ -1078,7 +1093,7 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(uint idx, table_map all_table_map= (((table_map) 1) << join->table_count) - 1; reset_validity_vars_for_keyuses(best_key_keyuse_ext_start, best_table, best_key, excluded_tables, true); - choose_plan(join, all_table_map & ~join->const_table_map); + choose_plan(join, all_table_map & ~join->const_table_map, 0); wrapper.end(); /* @@ -1111,64 +1126,74 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(uint idx, spl_opt_info->unsplit_card : 1); uint rec_len= table->s->rec_buff_length; - double split_card= spl_opt_info->unsplit_card * spl_plan->split_sel; - double oper_cost= split_card * - spl_postjoin_oper_cost(thd, split_card, rec_len); - spl_plan->cost= join->best_positions[join->table_count-1].read_time + - + oper_cost; + double oper_cost= (split_card * + spl_postjoin_oper_cost(thd, split_card, rec_len)); + spl_plan->cost= (join->best_positions[join->table_count-1].read_time + + oper_cost); + + chosen= (refills * spl_plan->cost + COST_EPS < + spl_opt_info->unsplit_cost); + if (unlikely(thd->trace_started())) + { + //psergey-merge:Json_writer_object wrapper(thd); + Json_writer_object find_trace(thd, "split_materialized"); + find_trace. + add("table", best_table->alias.c_ptr()). + add("key", best_table->key_info[best_key].name). + add("org_cost",join->best_positions[join->table_count-1].read_time). + add("postjoin_cost", oper_cost). + add("one_splitting_cost", spl_plan->cost). + add("unsplit_postjoin_cost", spl_opt_info->unsplit_oper_cost). + add("unsplit_cost", spl_opt_info->unsplit_cost). + add("rows", split_card). + add("refills", refills). + add("total_splitting_cost", refills * spl_plan->cost). + add("chosen", chosen); + } memcpy((char *) spl_plan->best_positions, (char *) join->best_positions, sizeof(POSITION) * join->table_count); reset_validity_vars_for_keyuses(best_key_keyuse_ext_start, best_table, best_key, excluded_tables, false); + already_printed= 1; } else - trace_obj.add("cached_plan_found", 1); - - if (spl_plan) { - if (unlikely(thd->trace_started())) - { - trace_obj. - add("lead_table", spl_plan->table->alias.ptr()). - add("index", spl_plan->table->key_info[spl_plan->key].name). - add("parts", spl_plan->parts). - add("split_sel", spl_plan->split_sel). - add("cost", spl_plan->cost). - add("unsplit_cost", spl_opt_info->unsplit_cost). - add("records", (ha_rows) (records * spl_plan->split_sel)); - } - - if (refills * spl_plan->cost < spl_opt_info->unsplit_cost - 0.01) - { - /* - The best plan that employs splitting is cheaper than - the plan without splitting - */ - spl_opt_info->last_plan= spl_plan; - spl_opt_info->last_refills= refills; - trace_obj.add("chosen", true); - } - else - trace_obj.add("chosen", false); + trace_obj.add("cached_plan_found", 1); + chosen= (refills * spl_plan->cost + COST_EPS < + spl_opt_info->unsplit_cost); + already_printed= 0; } } /* Set the cost of the preferred materialization for this partial join */ - records= (ha_rows)spl_opt_info->unsplit_card; - spl_plan= spl_opt_info->last_plan; - if (spl_plan) + if (chosen) { + /* + The best plan that employs splitting is cheaper than + the plan without splitting + */ startup_cost= spl_opt_info->last_refills * spl_plan->cost; - records= (ha_rows) (records * spl_plan->split_sel); + records= (ha_rows) (spl_opt_info->unsplit_card * spl_plan->split_sel); + if (unlikely(thd->trace_started()) && ! already_printed) + { + Json_writer_object trace(thd, "split_materialized"); + trace. + add("one_splitting_cost", spl_plan->cost). + add("total_splitting_cost", startup_cost). + add("rows", records); + } } else { - startup_cost= spl_opt_info->unsplit_cost; - *spl_pd_boundary= 0; + /* Restore original values */ + startup_cost= spl_opt_info->unsplit_cost; + records= (ha_rows) spl_opt_info->unsplit_card; + spl_plan= 0; } + return spl_plan; } |