diff options
-rw-r--r-- | sql/opt_subselect.cc | 10 | ||||
-rw-r--r-- | sql/sql_select.cc | 32 |
2 files changed, 28 insertions, 14 deletions
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index bdf5175fc8b..ae0c1e4f0a5 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -29,9 +29,9 @@ static TABLE_LIST *alloc_join_nest(THD *thd); static void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist); static uint get_tmp_table_rec_length(List<Item> &items); -static double get_tmp_table_lookup_cost(THD *thd, ha_rows row_count, +static double get_tmp_table_lookup_cost(THD *thd, double row_count, uint row_size); -static double get_tmp_table_write_cost(THD *thd, ha_rows row_count, +static double get_tmp_table_write_cost(THD *thd, double row_count, uint row_size); bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables); static SJ_MATERIALIZATION_INFO * @@ -1350,7 +1350,8 @@ static uint get_tmp_table_rec_length(List<Item> &items) @return the cost of one lookup */ -static double get_tmp_table_lookup_cost(THD *thd, ha_rows row_count, uint row_size) +static double +get_tmp_table_lookup_cost(THD *thd, double row_count, uint row_size) { if (row_count * row_size > thd->variables.max_heap_table_size) return (double) DISK_TEMPTABLE_LOOKUP_COST; @@ -1369,7 +1370,8 @@ static double get_tmp_table_lookup_cost(THD *thd, ha_rows row_count, uint row_si @return the cost of writing one row */ -static double get_tmp_table_write_cost(THD *thd, ha_rows row_count, uint row_size) +static double +get_tmp_table_write_cost(THD *thd, double row_count, uint row_size) { double lookup_cost= get_tmp_table_lookup_cost(thd, row_count, row_size); /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e1dfb4a3519..2e460c3d64a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -19727,12 +19727,9 @@ void JOIN::save_query_plan(Query_plan_state *save_to) if (keyuse.elements) { DYNAMIC_ARRAY tmp_keyuse; - // TODO: isn't this allocated by update_ref_and_keys - //if (my_init_dynamic_array(save_keyuse, sizeof(KEYUSE), 20, 64)) - // return 1; - /* Swap the current and the backup keyuse arrays. */ + /* Swap the current and the backup keyuse internal arrays. */ tmp_keyuse= keyuse; - keyuse= save_to->keyuse; + keyuse= save_to->keyuse; /* keyuse is reset to an empty array. */ save_to->keyuse= tmp_keyuse; for (uint i= 0; i < tables; i++) @@ -19785,9 +19782,9 @@ void JOIN::restore_query_plan(Query_plan_state *restore_from) @param save_to If != NULL, save here the state of the current query plan @notes - Given a query plan that already optimized taking into account some WHERE clause - 'C', reoptimize this plan with a new WHERE clause 'C AND added_where'. The - reoptimization works as follows: + Given a query plan that was already optimized taking into account some WHERE + clause 'C', reoptimize this plan with a new WHERE clause 'C AND added_where'. + The reoptimization works as follows: 1. Call update_ref_and_keys *only* for the new conditions 'added_where' that are about to be injected into the query. @@ -19808,6 +19805,7 @@ JOIN::reoptimize(Item *added_where, table_map join_tables, { DYNAMIC_ARRAY added_keyuse; SARGABLE_PARAM *sargables= 0; /* Used only as a dummy parameter. */ + uint org_keyuse_elements; /* Re-run the REF optimizer to take into account the new conditions. */ if (update_ref_and_keys(thd, &added_keyuse, join_tab, tables, added_where, @@ -19826,18 +19824,32 @@ JOIN::reoptimize(Item *added_where, table_map join_tables, if (save_to) save_query_plan(save_to); - /* Add the new access methods to the keyuse array. */ if (!keyuse.buffer && my_init_dynamic_array(&keyuse, sizeof(KEYUSE), 20, 64)) { delete_dynamic(&added_keyuse); return REOPT_ERROR; } - allocate_dynamic(&keyuse, keyuse.elements + added_keyuse.elements); + + org_keyuse_elements= save_to ? save_to->keyuse.elements : keyuse.elements; + allocate_dynamic(&keyuse, org_keyuse_elements + added_keyuse.elements); + + /* If needed, add the access methods from the original query plan. */ + if (save_to) + { + DBUG_ASSERT(!keyuse.elements); + memcpy(keyuse.buffer, + save_to->keyuse.buffer, + (size_t) save_to->keyuse.elements * keyuse.size_of_element); + keyuse.elements= save_to->keyuse.elements; + } + + /* Add the new access methods to the keyuse array. */ memcpy(keyuse.buffer + keyuse.elements * keyuse.size_of_element, added_keyuse.buffer, (size_t) added_keyuse.elements * added_keyuse.size_of_element); keyuse.elements+= added_keyuse.elements; + /* added_keyuse contents is copied, and it is no longer needed. */ delete_dynamic(&added_keyuse); if (sort_and_filter_keyuse(&keyuse)) |