revision-id: a3591d604f920a45ef6df9e3f37f11b9b300fd27 (mariadb-5.5.67-12-ga3591d6) parent(s): 280b158501fdb889beee3a0ea0b9acbf723acf66 author: Igor Babaev committer: Igor Babaev timestamp: 2020-04-17 20:32:46 -0700 message: Another attempt to fix bug MDEV-21932. The first patch for the bug was erroneous: it did not take into account the fact that the modified function get_key_scans_params() was called in different contexts. As a result the patch caused a regression bug MDEV-22191. The patch for this bug introduced an extra parameter. Actually we can do without this parameter and use the fourth parameter for the same puropose - to differentiate between the calls of the function for range access and for index merge access. Also removed the call of get_key_scans_params() in the code of the function merge_same_index_scans() as not needed. --- sql/opt_range.cc | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 9e96e94..5658bb0 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -948,9 +948,8 @@ QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index, uint mrr_buf_size, MEM_ROOT *alloc); static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, bool index_read_must_be_used, - bool update_tbl_stats, - double read_time, - bool ror_scans_required); + bool for_range_access, + double read_time); static TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree, double read_time); @@ -3147,7 +3146,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, /* Get best 'range' plan and prepare data for making other plans */ if ((range_trp= get_key_scans_params(¶m, tree, FALSE, TRUE, - best_read_time, FALSE))) + best_read_time))) { best_trp= range_trp; best_read_time= best_trp->read_cost; @@ -4673,7 +4672,6 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, double roru_index_costs; ha_rows roru_total_records; double roru_intersect_part= 1.0; - bool only_ror_scans_required= FALSE; DBUG_ENTER("get_best_disjunct_quick"); DBUG_PRINT("info", ("Full table scan cost: %g", read_time)); @@ -4700,8 +4698,6 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, n_child_scans))) DBUG_RETURN(NULL); - only_ror_scans_required= !optimizer_flag(param->thd, - OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION); /* Collect best 'range' scan for each of disjuncts, and, while doing so, analyze possibility of ROR scans. Also calculate some values needed by @@ -4714,8 +4710,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map, "tree in SEL_IMERGE");); if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, - read_time, - only_ror_scans_required))) + read_time))) { /* One of index scans in this index_merge is more expensive than entire @@ -5035,9 +5030,12 @@ TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge, a random order 2. the functions that estimate the cost of a range scan and an index merge retrievals are not well calibrated + + As the best range access has been already chosen it does not + make sense to evaluate the one obtained from a degenerated + index merge. */ - trp= get_key_scans_params(param, *imerge->trees, FALSE, TRUE, - read_time, FALSE); + trp= 0; } DBUG_RETURN(trp); @@ -6753,9 +6751,9 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, tree make range select for this SEL_TREE index_read_must_be_used if TRUE, assume 'index only' option will be set (except for clustered PK indexes) + for_range_access if TRUE the function is called to get the best range + plan for range access, not for index merge access read_time don't create read plans with cost > read_time. - only_ror_scans_required set to TRUE when we are only interested - in ROR scan RETURN Best range read plan NULL if no plan found or error occurred @@ -6763,9 +6761,8 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, bool index_read_must_be_used, - bool update_tbl_stats, - double read_time, - bool only_ror_scans_required) + bool for_range_access, + double read_time) { uint idx; SEL_ARG **key,**end, **key_to_read= NULL; @@ -6809,10 +6806,11 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, (bool) param->table->covering_keys.is_set(keynr); found_records= check_quick_select(param, idx, read_index_only, *key, - update_tbl_stats, &mrr_flags, + for_range_access, &mrr_flags, &buf_size, &cost); - if (only_ror_scans_required && !param->is_ror_scan) + if (!for_range_access && !param->is_ror_scan && + !optimizer_flag(param->thd,OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION)) { /* The scan is not a ROR-scan, just skip it */ continue;