From 4062fc28bd7c307d7a6b1987df071a3195b8e9b6 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 6 Oct 2021 12:31:19 +0300 Subject: [PATCH] Optimizer code cleanups, no logic changes - Updated comments - Added some extra DEBUG - Indentation changes and break long lines - Trivial code changes like: - Combining 2 statements in one - Reorder DBUG lines - Use a variable to store a pointer that is used multiple times - Moved declaration of variables to start of loop/function - Removed dead or commented code - Removed wrong DBUG_EXECUTE code in best_extension_by_limited_search() --- sql/filesort.cc | 14 +-- sql/multi_range_read.cc | 17 ++-- sql/opt_range.cc | 117 ++++++++++++--------- sql/opt_subselect.cc | 65 +++++------- sql/opt_subselect.h | 2 +- sql/opt_trace.cc | 47 ++++----- sql/rowid_filter.cc | 8 +- sql/sql_join_cache.cc | 2 +- sql/sql_lex.cc | 11 +- sql/sql_select.cc | 220 +++++++++++++++++++++++----------------- sql/sql_select.h | 4 +- sql/sql_update.cc | 6 +- 12 files changed, 283 insertions(+), 230 deletions(-) diff --git a/sql/filesort.cc b/sql/filesort.cc index bf5520955c9..f5345250987 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1544,7 +1544,7 @@ static bool check_if_pq_applicable(Sort_param *param, DBUG_RETURN(false); } - if (param->max_rows + 2 >= UINT_MAX) + if (param->max_rows >= UINT_MAX - 2) { DBUG_PRINT("info", ("Too large LIMIT")); DBUG_RETURN(false); @@ -2171,8 +2171,8 @@ Type_handler_timestamp_common::sort_length(THD *thd, void Type_handler_int_result::sort_length(THD *thd, - const Type_std_attributes *item, - SORT_FIELD_ATTR *sortorder) const + const Type_std_attributes *item, + SORT_FIELD_ATTR *sortorder) const { sortorder->original_length= sortorder->length= 8; // Sizof intern longlong } @@ -2180,8 +2180,8 @@ Type_handler_int_result::sort_length(THD *thd, void Type_handler_real_result::sort_length(THD *thd, - const Type_std_attributes *item, - SORT_FIELD_ATTR *sortorder) const + const Type_std_attributes *item, + SORT_FIELD_ATTR *sortorder) const { sortorder->original_length= sortorder->length= sizeof(double); } @@ -2205,8 +2205,8 @@ Type_handler_decimal_result::sort_length(THD *thd, @param thd Thread handler @param sortorder Order of items to sort @param s_length Number of items to sort - @param allow_packing_for_sortkeys [out] set to false if packing sort keys is not - allowed + @param allow_packing_for_sortkeys [out] set to false if packing sort keys + is not allowed @note * sortorder->length and other members are updated for each sort item. diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc index 2701dac56c4..0316caf9fdd 100644 --- a/sql/multi_range_read.cc +++ b/sql/multi_range_read.cc @@ -37,8 +37,8 @@ @param n_ranges_arg Number of ranges in the sequence, or 0 if the caller can't efficiently determine it @param bufsz INOUT IN: Size of the buffer available for use - OUT: Size of the buffer that is expected to be actually - used, or 0 if buffer is not needed. + OUT: Size of the buffer that is expected to be + actually used, or 0 if buffer is not needed. @param flags INOUT A combination of HA_MRR_* flags @param cost OUT Estimated cost of MRR access @@ -286,11 +286,15 @@ handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, (single_point_ranges - assigned_single_point_ranges). We don't add these to io_blocks as we don't want to penalize equal - readss (if we did, a range that would read 5 rows would be + reads (if we did, a range that would read 5 rows would be regarded as better than one equal read). Better to assume we have done a records_in_range() for the equal range and it's also cached. + + One effect of this is that io_blocks for simple ranges are often 0, + as the blocks where already read by records_in_range and we assume + that we don't have to read it again. */ io_blocks= (range_blocks_cnt - edge_blocks_cnt); unassigned_single_point_ranges+= (single_point_ranges - @@ -1991,9 +1995,10 @@ bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags, else { cost->reset(); - *buffer_size= (uint)MY_MAX(*buffer_size, - (size_t)(1.2*rows_in_last_step) * elem_size + - primary_file->ref_length + table->key_info[keynr].key_length); + *buffer_size= ((uint) MY_MAX(*buffer_size, + (size_t)(1.2*rows_in_last_step) * elem_size + + primary_file->ref_length + + table->key_info[keynr].key_length)); } Cost_estimate last_step_cost; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ddeb0e4fdbf..5e01b1272cc 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -19,8 +19,8 @@ Fix that MAYBE_KEY are stored in the tree so that we can detect use of full hash keys for queries like: - select s.id, kws.keyword_id from sites as s,kws where s.id=kws.site_id and kws.keyword_id in (204,205); - + select s.id, kws.keyword_id from sites as s,kws where s.id=kws.site_id and + kws.keyword_id in (204,205); */ /* @@ -2626,7 +2626,8 @@ static int fill_used_fields_bitmap(PARAM *param) In the table struct the following information is updated: quick_keys - Which keys can be used quick_rows - How many rows the key matches - opt_range_condition_rows - E(# rows that will satisfy the table condition) + opt_range_condition_rows - E(# rows that will satisfy the table + condition) IMPLEMENTATION opt_range_condition_rows value is obtained as follows: @@ -2774,7 +2775,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, thd->no_errors=1; // Don't warn about NULL init_sql_alloc(key_memory_quick_range_select_root, &alloc, - thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC)); + thd->variables.range_alloc_block_size, 0, + MYF(MY_THREAD_SPECIFIC)); if (!(param.key_parts= (KEY_PART*) alloc_root(&alloc, sizeof(KEY_PART) * @@ -2931,6 +2933,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, TRP_INDEX_INTERSECT *intersect_trp; bool can_build_covering= FALSE; Json_writer_object trace_range(thd, "analyzing_range_alternatives"); + TABLE_READ_PLAN *range_trp; backup_keys= (SEL_ARG**) alloca(sizeof(backup_keys[0])*param.keys); memcpy(&backup_keys[0], &tree->keys[0], @@ -2939,9 +2942,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, remove_nonrange_trees(¶m, tree); /* Get best 'range' plan and prepare data for making other plans */ - if (auto range_trp= get_key_scans_params(¶m, tree, - only_single_index_range_scan, - true, best_read_time)) + if ((range_trp= get_key_scans_params(¶m, tree, + only_single_index_range_scan, + true, best_read_time))) { best_trp= range_trp; best_read_time= best_trp->read_cost; @@ -3048,7 +3051,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, { grp_summary.add("chosen", true); best_trp= group_trp; - best_read_time= best_trp->read_cost; } else grp_summary.add("chosen", false).add("cause", "cost"); @@ -3112,7 +3114,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, SYNOPSIS create_key_parts_for_pseudo_indexes() param IN/OUT data structure for the descriptors to be built - used_fields bitmap of columns for which the descriptors are to be built + used_fields bitmap of columns for which the descriptors are to be built DESCRIPTION For each column marked in the bitmap used_fields the function builds @@ -3209,9 +3211,10 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param, SYNOPSIS records_in_column_ranges() param the data structure to access descriptors of pseudo indexes - built over columns used in the condition of the processed query + built over columns used in the condition of the processed + query idx the index of the descriptor of interest in param - tree the tree representing ranges built for the interesting column + tree the tree representing ranges built for the interesting column DESCRIPTION This function retrieves the ranges represented by the SEL_ARG 'tree' and @@ -3334,7 +3337,8 @@ int cmp_quick_ranges(TABLE *table, uint *a, uint *b) DESCRIPTION This function calculates the selectivity of range conditions cond imposed on the rows of 'table' in the processed query. - The calculated selectivity is assigned to the field table->cond_selectivity. + The calculated selectivity is assigned to the field + table->cond_selectivity. Selectivity is calculated as a product of selectivities imposed by: @@ -3346,6 +3350,8 @@ int cmp_quick_ranges(TABLE *table, uint *a, uint *b) 3. Reading a few records from the table pages and checking the condition selectivity (this is used for conditions like "column LIKE '%val%'" where approaches #1 and #2 do not provide selectivity data). + 4. If the selectivity calculated by get_best_ror_intersect() is smaller, + use this instead. NOTE Currently the selectivities of range conditions over different columns are @@ -3362,6 +3368,9 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) MY_BITMAP *used_fields= &table->cond_set; double table_records= (double)table->stat_records(); uint optimal_key_order[MAX_KEY]; + MY_BITMAP handled_columns; + my_bitmap_map *buf; + QUICK_SELECT_I *quick; DBUG_ENTER("calculate_cond_selectivity_for_table"); table->cond_selectivity= 1.0; @@ -3369,7 +3378,6 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) if (table_records == 0) DBUG_RETURN(FALSE); - QUICK_SELECT_I *quick; if ((quick=table->reginfo.join_tab->quick) && quick->get_type() == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX) { @@ -3377,14 +3385,14 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) DBUG_RETURN(FALSE); } - if (!*cond) + if (!*cond || table->pos_in_table_list->schema_table) DBUG_RETURN(FALSE); - if (table->pos_in_table_list->schema_table) - DBUG_RETURN(FALSE); - - MY_BITMAP handled_columns; - my_bitmap_map* buf; + /* + This should be pre-alloced so that we could use the same bitmap for all + tables. Would also avoid extra memory allocations if this function would + be called multiple times per query. + */ if (!(buf= (my_bitmap_map*)thd->alloc(table->s->column_bitmap_size))) DBUG_RETURN(TRUE); my_bitmap_init(&handled_columns, buf, table->s->fields); @@ -3512,7 +3520,8 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) double rows; init_sql_alloc(key_memory_quick_range_select_root, &alloc, - thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC)); + thd->variables.range_alloc_block_size, 0, + MYF(MY_THREAD_SPECIFIC)); param.thd= thd; param.mem_root= &alloc; param.old_root= thd->mem_root; @@ -3531,9 +3540,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) thd->no_errors=1; - tree= cond[0]->get_mm_tree(¶m, cond); - - if (!tree) + if (!(tree= cond[0]->get_mm_tree(¶m, cond))) goto free_alloc; table->reginfo.impossible_range= 0; @@ -3557,7 +3564,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) for (uint idx= 0; idx < param.keys; idx++) { SEL_ARG *key= tree->keys[idx]; - if (key) + if (key) // Quick range found for key { Json_writer_object selectivity_for_column(thd); selectivity_for_column.add("column_name", key->field->field_name); @@ -5671,8 +5678,7 @@ bool create_fields_bitmap(PARAM *param, MY_BITMAP *fields_bitmap) static int cmp_intersect_index_scan(INDEX_SCAN_INFO **a, INDEX_SCAN_INFO **b) { - return (*a)->records < (*b)->records ? - -1 : (*a)->records == (*b)->records ? 0 : 1; + return CMP_NUM((*a)->records, (*b)->records); } @@ -6269,7 +6275,8 @@ bool check_index_intersect_extension(PARTIAL_INDEX_INTERSECT_INFO *curr, size_t max_memory_size= common_info->max_memory_size; records_sent_to_unique+= ext_index_scan_records; - cost= Unique::get_use_cost(buff_elems, (size_t) records_sent_to_unique, key_size, + cost= Unique::get_use_cost(buff_elems, (size_t) records_sent_to_unique, + key_size, max_memory_size, compare_factor, TRUE, &next->in_memory); if (records_filtered_out_by_cpk) @@ -6584,6 +6591,11 @@ ROR_SCAN_INFO *make_ror_scan(const PARAM *param, int idx, SEL_ARG *sel_arg) if (bitmap_is_set(¶m->needed_fields, key_part->fieldnr-1)) bitmap_set_bit(&ror_scan->covered_fields, key_part->fieldnr-1); } + + /* + Cost of reading the keys for the rows, which are later stored in the + ror queue. + */ ror_scan->index_read_cost= param->table->file->keyread_time(ror_scan->keynr, 1, ror_scan->records); DBUG_RETURN(ror_scan); @@ -6895,7 +6907,7 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info, avoid duplicating the inference code) NOTES - Adding a ROR scan to ROR-intersect "makes sense" iff the cost of ROR- + Adding a ROR scan to ROR-intersect "makes sense" if the cost of ROR- intersection decreases. The cost of ROR-intersection is calculated as follows: @@ -7057,8 +7069,12 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, { uint idx; double min_cost= DBL_MAX; - DBUG_ENTER("get_best_ror_intersect"); THD *thd= param->thd; + DBUG_ENTER("get_best_ror_intersect"); + DBUG_PRINT("enter", ("opt_range_condition_rows: %llu cond_selectivity: %g", + (ulonglong) param->table->opt_range_condition_rows, + param->table->cond_selectivity)); + Json_writer_object trace_ror(thd, "analyzing_roworder_intersect"); if ((tree->n_ror_scans < 2) || !param->table->stat_records() || @@ -7267,6 +7283,8 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, ? "too few indexes to merge" : "cost"); } + DBUG_PRINT("enter", ("opt_range_condition_rows: %llu", + (ulonglong) param->table->opt_range_condition_rows)); DBUG_RETURN(trp); } @@ -11535,7 +11553,8 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only, bool *is_ror_scan) { SEL_ARG_RANGE_SEQ seq; - RANGE_SEQ_IF seq_if = {NULL, sel_arg_range_seq_init, sel_arg_range_seq_next, 0, 0}; + RANGE_SEQ_IF seq_if= + {NULL, sel_arg_range_seq_init, sel_arg_range_seq_next, 0, 0}; handler *file= param->table->file; ha_rows rows= HA_POS_ERROR; uint keynr= param->real_keynr[idx]; @@ -11603,24 +11622,24 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only, This check is needed as sometimes that table statistics or range estimates may be slightly out of sync. */ - rows= table_records; - set_if_bigger(rows, 1); + rows= MY_MAX(table_records, 1); param->quick_rows[keynr]= rows; } param->possible_keys.set_bit(keynr); if (update_tbl_stats) { + TABLE::OPT_RANGE *range= param->table->opt_range + keynr; param->table->opt_range_keys.set_bit(keynr); - param->table->opt_range[keynr].key_parts= param->max_key_parts; - param->table->opt_range[keynr].ranges= param->range_count; + range->key_parts= param->max_key_parts; + range->ranges= param->range_count; param->table->opt_range_condition_rows= MY_MIN(param->table->opt_range_condition_rows, rows); - param->table->opt_range[keynr].rows= rows; - param->table->opt_range[keynr].cost= cost->total_cost(); + range->rows= rows; + range->cost= cost->total_cost(); if (param->table->file->is_clustering_key(keynr)) - param->table->opt_range[keynr].index_only_cost= 0; + range->index_only_cost= 0; else - param->table->opt_range[keynr].index_only_cost= cost->index_only_cost(); + range->index_only_cost= cost->index_only_cost(); } } @@ -14821,11 +14840,13 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, set_if_smaller(num_groups, table_records); if (used_key_parts > group_key_parts) - { /* + { + /* Compute the probability that two ends of a subgroup are inside different blocks. */ - keys_per_subgroup= (ha_rows) index_info->actual_rec_per_key(used_key_parts - 1); + keys_per_subgroup= (ha_rows) index_info->actual_rec_per_key(used_key_parts - + 1); if (keys_per_subgroup >= keys_per_block) /* If a subgroup is bigger than */ p_overlap= 1.0; /* a block, it will overlap at least two blocks. */ else @@ -14849,10 +14870,13 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, reads the next record without having to re-position to it on every group. To make the CPU cost reflect this, we estimate the CPU cost as the sum of: - 1. Cost for evaluating the condition (similarly as for index scan). + 1. Cost for evaluating the condition for each num_group + (1/TIME_FOR_COMPARE) (similarly as for index scan). 2. Cost for navigating the index structure (assuming a b-tree). - Note: We only add the cost for one comparision per block. For a - b-tree the number of comparisons will be larger. + Note: We only add the cost for one index comparision per block. For a + b-tree the number of comparisons will be larger. However the cost + is low as all of the upper level b-tree blocks should be in + memory. TODO: This cost should be provided by the storage engine. */ const double tree_traversal_cost= @@ -14860,8 +14884,8 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, log(static_cast(keys_per_block))) * 1/(2*TIME_FOR_COMPARE); - const double cpu_cost= num_groups * - (tree_traversal_cost + 1/TIME_FOR_COMPARE_IDX); + const double cpu_cost= (num_groups * + (tree_traversal_cost + 1/TIME_FOR_COMPARE_IDX)); *read_cost= io_cost + cpu_cost; *records= num_groups; @@ -14910,7 +14934,8 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows, group_prefix_len, group_key_parts, used_key_parts, index_info, index, read_cost, records, key_infix_len, - key_infix, parent_alloc, is_index_scan); + key_infix, parent_alloc, + is_index_scan); if (!quick) DBUG_RETURN(NULL); diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 3e2531b90cd..6ec32ae0e73 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -2507,24 +2507,13 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map) sjm->is_used= FALSE; double subjoin_out_rows, subjoin_read_time; - /* - join->get_partial_cost_and_fanout(n_tables + join->const_tables, - table_map(-1), - &subjoin_read_time, - &subjoin_out_rows); - */ - join->get_prefix_cost_and_fanout(n_tables, + join->get_prefix_cost_and_fanout(n_tables, &subjoin_read_time, &subjoin_out_rows); sjm->materialization_cost.convert_from_cost(subjoin_read_time); sjm->rows_with_duplicates= sjm->rows= subjoin_out_rows; - // Don't use the following list because it has "stale" items. use - // ref_pointer_array instead: - // - //List &right_expr_list= - // sj_nest->sj_subq_pred->unit->first_select()->item_list; /* Adjust output cardinality estimates. If the subquery has form @@ -3432,8 +3421,8 @@ bool Firstmatch_picker::check_qep(JOIN *join, optimizer_flag(join->thd, OPTIMIZER_SWITCH_SEMIJOIN_WITH_CACHE)) { /* - An important special case: only one inner table, and @@optimizer_switch - allows join buffering. + An important special case: only one inner table, and + @@optimizer_switch allows join buffering. - read_time is the same (i.e. FirstMatch doesn't add any cost - remove fanout added by the last table */ @@ -3583,8 +3572,7 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join, Add the cost of temptable use. The table will have sj_outer_fanout records, and we will make - sj_outer_fanout table writes - - sj_inner_fanout*sj_outer_fanout lookups. - + - sj_inner_fanout*sj_outer_fanout lookups. */ double one_lookup_cost= get_tmp_table_lookup_cost(join->thd, sj_outer_fanout, @@ -3657,33 +3645,37 @@ void JOIN::dbug_verify_sj_inner_tables(uint prefix_size) const */ void restore_prev_sj_state(const table_map remaining_tables, - const JOIN_TAB *tab, uint idx) + const JOIN_TAB *tab, uint idx) { TABLE_LIST *emb_sj_nest; - if (tab->emb_sj_nest) + if ((emb_sj_nest= tab->emb_sj_nest)) { - table_map subq_tables= tab->emb_sj_nest->sj_inner_tables; + table_map subq_tables= emb_sj_nest->sj_inner_tables; tab->join->sjm_lookup_tables &= ~subq_tables; - } - if (!tab->join->emb_sjm_nest && (emb_sj_nest= tab->emb_sj_nest)) - { - table_map subq_tables= emb_sj_nest->sj_inner_tables & - ~tab->join->const_table_map; - /* If we're removing the last SJ-inner table, remove the sj-nest */ - if ((remaining_tables & subq_tables) == subq_tables) + if (!tab->join->emb_sjm_nest) { - // All non-const tables of the SJ nest are in the remaining_tables. - // we are not in the nest anymore. - tab->join->cur_sj_inner_tables &= ~emb_sj_nest->sj_inner_tables; - } - else - { - // Semi-join nest has: - // - a table being removed (not in the prefix) - // - some tables in the prefix. - tab->join->cur_sj_inner_tables |= emb_sj_nest->sj_inner_tables; + table_map subq_tables= (emb_sj_nest->sj_inner_tables & + ~tab->join->const_table_map); + /* If we're removing the last SJ-inner table, remove the sj-nest */ + if ((remaining_tables & subq_tables) == subq_tables) + { + /* + All non-const tables of the SJ nest are in the remaining_tables. + we are not in the nest anymore. + */ + tab->join->cur_sj_inner_tables &= ~emb_sj_nest->sj_inner_tables; + } + else + { + /* + Semi-join nest has: + - a table being removed (not in the prefix) + - some tables in the prefix. + */ + tab->join->cur_sj_inner_tables |= emb_sj_nest->sj_inner_tables; + } } } @@ -6634,7 +6626,6 @@ bool JOIN::choose_subquery_plan(table_map join_tables) /* Get the cost of the modified IN-EXISTS plan. */ inner_read_time_2= inner_join->best_read; - } else { diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index 7b1b810ee81..cc6d2fbbecb 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -320,7 +320,7 @@ void optimize_semi_joins(JOIN *join, table_map remaining_tables, uint idx, void update_sj_state(JOIN *join, const JOIN_TAB *new_tab, uint idx, table_map remaining_tables); void restore_prev_sj_state(const table_map remaining_tables, - const JOIN_TAB *tab, uint idx); + const JOIN_TAB *tab, uint idx); void fix_semijoin_strategies_for_picked_join_order(JOIN *join); diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc index 4bc493940fb..a7e8c3da63b 100644 --- a/sql/opt_trace.cc +++ b/sql/opt_trace.cc @@ -568,35 +568,32 @@ void Opt_trace_stmt::set_allowed_mem_size(size_t mem_size) void Json_writer::add_table_name(const JOIN_TAB *tab) { + char table_name_buffer[SAFE_NAME_LEN]; + DBUG_ASSERT(tab != NULL); DBUG_ASSERT(tab->join->thd->trace_started()); - if (tab != NULL) + + if (tab->table && tab->table->derived_select_number) { - char table_name_buffer[SAFE_NAME_LEN]; - if (tab->table && tab->table->derived_select_number) - { - /* Derived table name generation */ - size_t len= my_snprintf(table_name_buffer, sizeof(table_name_buffer)-1, - "", - tab->table->derived_select_number); - add_str(table_name_buffer, len); - } - else if (tab->bush_children) - { - JOIN_TAB *ctab= tab->bush_children->start; - size_t len= my_snprintf(table_name_buffer, - sizeof(table_name_buffer)-1, - "", - ctab->emb_sj_nest->sj_subq_pred->get_identifier()); - add_str(table_name_buffer, len); - } - else - { - TABLE_LIST *real_table= tab->table->pos_in_table_list; - add_str(real_table->alias.str, real_table->alias.length); - } + /* Derived table name generation */ + size_t len= my_snprintf(table_name_buffer, sizeof(table_name_buffer)-1, + "", + tab->table->derived_select_number); + add_str(table_name_buffer, len); + } + else if (tab->bush_children) + { + JOIN_TAB *ctab= tab->bush_children->start; + size_t len= my_snprintf(table_name_buffer, + sizeof(table_name_buffer)-1, + "", + ctab->emb_sj_nest->sj_subq_pred->get_identifier()); + add_str(table_name_buffer, len); } else - DBUG_ASSERT(0); + { + TABLE_LIST *real_table= tab->table->pos_in_table_list; + add_str(real_table->alias.str, real_table->alias.length); + } } void Json_writer::add_table_name(const TABLE *table) diff --git a/sql/rowid_filter.cc b/sql/rowid_filter.cc index 0589b587ba2..c775bdf35d6 100644 --- a/sql/rowid_filter.cc +++ b/sql/rowid_filter.cc @@ -39,7 +39,8 @@ double Range_rowid_filter_cost_info::lookup_cost( /** @brief - The average gain in cost per row to use the range filter with this cost info + The average gain in cost per row to use the range filter with this cost + info */ inline @@ -58,8 +59,9 @@ double Range_rowid_filter_cost_info::avg_access_and_eval_gain_per_row( @param access_cost_factor the adjusted cost of access a row @details - The current code to estimate the cost of a ref access is quite inconsistent: - in some cases the effect of page buffers is taken into account, for others + The current code to estimate the cost of a ref access is quite + inconsistent: + In some cases the effect of page buffers is taken into account, for others just the engine dependent read_time() is employed. That's why the average cost of one random seek might differ from 1. The parameter access_cost_factor can be considered as the cost of a random diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index c7b6a0bf6e4..45419d7e5b1 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -1080,7 +1080,7 @@ int JOIN_CACHE::init(bool for_explain) /* - Check the possibility to read the access keys directly from the join buffer + Check the possibility to read the access keys directly from the join buffer SYNOPSIS check_emb_key_usage() diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index e3f486486d7..3707b8ef8e4 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -5956,7 +5956,7 @@ unit_common_op st_select_lex_unit::common_op() else { if (operation != op) - operation= OP_MIX; + return OP_MIX; } } } @@ -5966,12 +5966,13 @@ unit_common_op st_select_lex_unit::common_op() Save explain structures of a UNION. The only variable member is whether the union has "Using filesort". - There is also save_union_explain_part2() function, which is called before we read - UNION's output. + There is also save_union_explain_part2() function, which is called before we + read UNION's output. The reason for it is examples like this: - SELECT col1 FROM t1 UNION SELECT col2 FROM t2 ORDER BY (select ... from t3 ...) + SELECT col1 FROM t1 UNION SELECT col2 FROM t2 + ORDER BY (select ... from t3 ...) Here, the (select ... from t3 ...) subquery must be a child of UNION's st_select_lex. However, it is not connected as child until a very late @@ -10191,7 +10192,7 @@ SELECT_LEX_UNIT *LEX::parsed_select_expr_cont(SELECT_LEX_UNIT *unit, /** Add primary expression as the next term in a given query expression body - pruducing a new query expression body + producing a new query expression body */ SELECT_LEX_UNIT * diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 87796d53991..a3175dd0769 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1990,9 +1990,8 @@ bool JOIN::make_range_rowid_filters() bool JOIN::init_range_rowid_filters() { - DBUG_ENTER("init_range_rowid_filters"); - JOIN_TAB *tab; + DBUG_ENTER("init_range_rowid_filters"); for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; @@ -2248,7 +2247,8 @@ JOIN::optimize_inner() (see build_equal_items() below) because it can be not rebuilt at second invocation. */ - if (!thd->stmt_arena->is_conventional() && thd->mem_root != thd->stmt_arena->mem_root) + if (!thd->stmt_arena->is_conventional() && + thd->mem_root != thd->stmt_arena->mem_root) for (TABLE_LIST *tbl= tables_list; tbl; tbl= tbl->next_local) if (tbl->table && tbl->on_expr && tbl->table->versioned()) { @@ -5318,6 +5318,7 @@ make_join_statistics(JOIN *join, List &tables_list, s->tab_list= tables; table->pos_in_table_list= tables; error= tables->fetch_number_of_rows(); + /* Calculate table->use_stat_records */ set_statistics_for_table(join->thd, table); bitmap_clear_all(&table->cond_set); @@ -5987,7 +5988,6 @@ make_join_statistics(JOIN *join, List &tables_list, DBUG_RETURN(TRUE); /* purecov: inspected */ { - double records= 1; SELECT_LEX_UNIT *unit= join->select_lex->master_unit(); /* Find an optimal join order of the non-constant tables. */ @@ -6018,10 +6018,12 @@ make_join_statistics(JOIN *join, List &tables_list, Calculate estimated number of rows for materialized derived table/view. */ + double records= 1.0; + ha_rows rows; for (i= 0; i < join->table_count ; i++) if (double rr= join->best_positions[i].records_read) records= COST_MULT(records, rr); - ha_rows rows= records > (double) HA_ROWS_MAX ? HA_ROWS_MAX : (ha_rows) records; + rows= records > (double) HA_ROWS_MAX ? HA_ROWS_MAX : (ha_rows) records; set_if_smaller(rows, unit->lim.get_select_limit()); join->select_lex->increase_derived_records(rows); } @@ -6369,8 +6371,8 @@ add_key_field(JOIN *join, Field op formula Field IS NULL Field IS NOT NULL - Field BETWEEN ... - Field IN ... + Field BETWEEN ... + Field IN ... */ if (field->flags & PART_KEY_FLAG) { @@ -6458,10 +6460,10 @@ add_key_field(JOIN *join, @param field_item Field item used for comparison @param eq_func True if we used =, <=> or IS NULL @param value Value used for comparison with field_item - @param num_values Number of values[] that we are comparing against + @param num_values Number of values[] that we are comparing against @param usable_tables Tables which can be used for key optimization @param sargables IN/OUT Array of found sargable candidates - @param row_col_no if = n that > 0 then field is compared only + @param row_col_no if = n that > 0 then field is compared only against the n-th component of row values @note @@ -7690,20 +7692,30 @@ void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key) Estimate how many records we will get if we read just this table and apply a part of WHERE that can be checked for it. - @detail + @param s Current JOIN_TAB + @param with_found_constraint There is a filtering condition on the + current table. See more below + @param use_cond_selectivity Value of optimizer_use_condition_selectivity. + If > 1 then use table->cond_selecitivity. + + @return 0.0 No matching rows + @return >= 1.0 Number of expected matching rows + + @details Estimate how many records we will get if we - read the given table with its "independent" access method (either quick select or full table/index scan), - apply the part of WHERE that refers only to this table. + - The result cannot be bigger than table records - @seealso - table_cond_selectivity() produces selectivity of condition that is checked - after joining rows from this table to rows from preceding tables. + @see also + table_after_join_selectivity() produces selectivity of condition that is + checked after joining rows from this table to rows from preceding tables. */ inline double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint, - uint use_cond_selectivity) + uint use_cond_selectivity) { ha_rows records; double dbl_records; @@ -7804,7 +7816,7 @@ double adjust_quick_cost(double quick_cost, ha_rows records) The function finds the best access path to table 's' from the passed partial plan where an access path is the general term for any means to - access the data in 's'. An access path may use either an index or a scan, + cacess the data in 's'. An access path may use either an index or a scan, whichever is cheaper. The input partial plan is passed via the array 'join->positions' of length 'idx'. The chosen access method for 's' and its cost are stored in 'join->positions[idx]'. @@ -7838,14 +7850,16 @@ best_access_path(JOIN *join, POSITION *loose_scan_pos) { THD *thd= join->thd; - uint use_cond_selectivity= thd->variables.optimizer_use_condition_selectivity; + uint use_cond_selectivity= + thd->variables.optimizer_use_condition_selectivity; KEYUSE *best_key= 0; uint best_max_key_part= 0; my_bool found_constraint= 0; double best= DBL_MAX; double best_time= DBL_MAX; double records= DBL_MAX; - ha_rows records_for_key= 0; + ha_rows records_for_key; + double best_filter_cmp_gain; table_map best_ref_depends_map= 0; /* key_dependent is 0 if all key parts could be used or if there was an @@ -7947,7 +7961,7 @@ best_access_path(JOIN *join, do /* For each way to access the keypart */ { /* - if 1. expression doesn't refer to forward tables + If 1. expression does not refer to forward tables 2. we won't get two ref-or-null's */ all_parts|= keyuse->keypart_map; @@ -7970,7 +7984,8 @@ best_access_path(JOIN *join, (found_ref | keyuse->used_tables)); if (tmp2 < best_prev_record_reads) { - best_part_found_ref= keyuse->used_tables & ~join->const_table_map; + best_part_found_ref= (keyuse->used_tables & + ~join->const_table_map); best_prev_record_reads= tmp2; } if (rec > keyuse->ref_table_rows) @@ -8189,7 +8204,7 @@ best_access_path(JOIN *join, We also have a property that "range optimizer produces equal or tighter set of scan intervals than ref(const) optimizer". Each of the intervals in (**) are "tightest possible" intervals when - one limits itself to using keyparts 1..K (which we do in #2). + one limits itself to using keyparts 1..K (which we do in #2). From here it follows that range access used either one, or both of the (I1) and (I2) intervals: @@ -8243,7 +8258,8 @@ best_access_path(JOIN *join, if (!found_ref && // (1) records < rows) // (3) { - trace_access_idx.add("used_range_estimates", "clipped up"); + trace_access_idx.add("used_range_estimates", + "clipped up"); records= rows; } } @@ -8483,7 +8499,8 @@ best_access_path(JOIN *join, join->allowed_outer_join_with_cache)) // (2) { double join_sel= 0.1; - /* Estimate the cost of the hash join access to the table */ + double refills; + /* Estimate the cost of the hash join access to the table */ double rnd_records= matching_candidates_in_table(s, found_constraint, use_cond_selectivity); @@ -8492,10 +8509,9 @@ best_access_path(JOIN *join, tmp= COST_ADD(tmp, cmp_time); /* We read the table as many times as join buffer becomes full. */ - - double refills= (1.0 + floor((double) cache_record_length(join,idx) * - record_count / - (double) thd->variables.join_buff_size)); + refills= (1.0 + floor((double) cache_record_length(join,idx) * + record_count / + (double) thd->variables.join_buff_size)); tmp= COST_MULT(tmp, refills); best_time= COST_ADD(tmp, COST_MULT((record_count*join_sel) / TIME_FOR_COMPARE, @@ -8578,7 +8594,11 @@ best_access_path(JOIN *join, For each record we: - read record range through 'quick' - skip rows which does not satisfy WHERE constraints - TODO: + + Note that s->quick->read_time includes the cost of comparing + the row with the where clause (TIME_FOR_COMPARE) + + TODO: We take into account possible use of join cache for ALL/index access (see first else-branch below), but we don't take it into account here for range/index_merge access. Find out why this is so. @@ -8638,9 +8658,13 @@ best_access_path(JOIN *join, if ((s->table->map & join->outer_join) || disable_jbuf) // Can't use join cache { /* + Simple scan + For each record we have to: - - read the whole table record - - skip rows which does not satisfy join condition + - Read the whole table record + - Compare with the current where clause with only fields for the table + - Compare with the full where and skip rows which does not satisfy + the join condition */ double cmp_time= (s->records - rnd_records)/TIME_FOR_COMPARE; tmp= COST_MULT(record_count, COST_ADD(tmp,cmp_time)); @@ -8678,9 +8702,9 @@ best_access_path(JOIN *join, tmp give us total cost of using TABLE SCAN */ - const double best_filter_cmp_gain= best_filter - ? best_filter->get_cmp_gain(record_count * records) - : 0; + best_filter_cmp_gain= (best_filter ? + best_filter->get_cmp_gain(record_count * records) : + 0); trace_access_scan.add("resulting_rows", rnd_records); trace_access_scan.add("cost", tmp); @@ -8792,6 +8816,7 @@ static void choose_initial_table_order(JOIN *join) JOIN_TAB **tab= join->best_ref + join->const_tables; JOIN_TAB **tabs_end= tab + join->table_count - join->const_tables; DBUG_ENTER("choose_initial_table_order"); + /* Find where the top-level JOIN_TABs end and subquery JOIN_TABs start */ for (; tab != tabs_end; tab++) { @@ -8908,10 +8933,10 @@ choose_plan(JOIN *join, table_map join_tables) /* if (SELECT_STRAIGHT_JOIN option is set) reorder tables so dependent tables come after tables they depend - on, otherwise keep tables in the order they were specified in the query + on, otherwise keep tables in the order they were specified in the query else - Apply heuristic: pre-sort all access plans with respect to the number of - records accessed. + Apply heuristic: pre-sort all access plans with respect to the number + of records accessed. */ jtab_sort_func= straight_join ? join_tab_cmp_straight : join_tab_cmp; } @@ -9992,7 +10017,7 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, Selectivity of COND(table) is already accounted for in matching_candidates_in_table(). */ - sel= 1; + sel= 1.0; } /* @@ -10015,7 +10040,8 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, next_field != field; next_field= next_field->next_equal_field) { - if (!(next_field->table->map & rem_tables) && next_field->table != table) + if (!(next_field->table->map & rem_tables) && + next_field->table != table) { if (field->cond_selectivity > 0) { @@ -10329,9 +10355,8 @@ best_extension_by_limited_search(JOIN *join, SORT_POSITION *sort= (SORT_POSITION*) alloca(sizeof(SORT_POSITION)*tables_left); SORT_POSITION *sort_end; DBUG_ENTER("best_extension_by_limited_search"); - DBUG_EXECUTE_IF("show_explain_probe_best_ext_lim_search", - if (dbug_user_var_equals_int(thd, + if (dbug_user_var_equals_int(thd, "show_explain_probe_select_id", join->select_lex->select_number)) dbug_serve_apcs(thd, 1); @@ -10434,6 +10459,8 @@ best_extension_by_limited_search(JOIN *join, double current_record_count, current_read_time; double partial_join_cardinality; POSITION *position= join->positions + idx, *loose_scan_pos; + double filter_cmp_gain; + double pushdown_cond_selectivity; Json_writer_object trace_one_table(thd); if (unlikely(thd->trace_started())) @@ -10448,9 +10475,9 @@ best_extension_by_limited_search(JOIN *join, /* Compute the cost of the new plan extended with 's' */ current_record_count= COST_MULT(record_count, position->records_read); - const double filter_cmp_gain= position->range_rowid_filter_info - ? position->range_rowid_filter_info->get_cmp_gain(current_record_count) - : 0; + filter_cmp_gain= position->range_rowid_filter_info ? + position->range_rowid_filter_info->get_cmp_gain(current_record_count) : + 0; current_read_time= COST_ADD(read_time, COST_ADD(position->read_time - filter_cmp_gain, @@ -10574,7 +10601,7 @@ best_extension_by_limited_search(JOIN *join, } } - double pushdown_cond_selectivity= 1.0; + pushdown_cond_selectivity= 1.0; if (use_cond_selectivity > 1) pushdown_cond_selectivity= table_cond_selectivity(join, idx, s, remaining_tables & @@ -10977,7 +11004,7 @@ prev_record_reads(const POSITION *positions, uint idx, table_map found_ref) found= COST_MULT(found, pos->records_read); found*= pos->cond_selectivity; } - } + } } return found; } @@ -11397,14 +11424,15 @@ bool JOIN::get_best_combination() j->table= NULL; //temporary way to tell SJM tables from others. j->ref.key = -1; j->on_expr_ref= (Item**) &null_ptr; - j->keys= key_map(1); /* The unique index is always in 'possible keys' in EXPLAIN */ + /* The unique index is always in 'possible keys' in EXPLAIN */ + j->keys= key_map(1); /* 2. Proceed with processing SJM nest's join tabs, putting them into the sub-order */ SJ_MATERIALIZATION_INFO *sjm= cur_pos->table->emb_sj_nest->sj_mat_info; - j->records_read= (sjm->is_sj_scan? sjm->rows : 1); + j->records_read= (sjm->is_sj_scan? sjm->rows : 1.0); j->records= (ha_rows) j->records_read; j->cond_selectivity= 1.0; JOIN_TAB *jt; @@ -11430,9 +11458,9 @@ bool JOIN::get_best_combination() form->reginfo.join_tab=j; DBUG_PRINT("info",("type: %d", j->type)); if (j->type == JT_CONST) - goto loop_end; // Handled in make_join_stat.. + goto loop_end; // Handled in make_join_stat.. - j->loosescan_match_tab= NULL; //non-nulls will be set later + j->loosescan_match_tab= NULL; //non-nulls will be set later j->inside_loosescan_range= FALSE; j->ref.key = -1; j->ref.key_parts=0; @@ -11447,18 +11475,12 @@ bool JOIN::get_best_combination() full_join= 1; } - /*if (best_positions[tablenr].sj_strategy == SJ_OPT_LOOSE_SCAN) - { - DBUG_ASSERT(!keyuse || keyuse->key == - best_positions[tablenr].loosescan_picker.loosescan_key); - j->index= best_positions[tablenr].loosescan_picker.loosescan_key; - }*/ - if ((j->type == JT_REF || j->type == JT_EQ_REF) && is_hash_join_key_no(j->ref.key)) hash_join= TRUE; - j->range_rowid_filter_info= best_positions[tablenr].range_rowid_filter_info; + j->range_rowid_filter_info= + best_positions[tablenr].range_rowid_filter_info; loop_end: /* @@ -12583,7 +12605,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) tab->type == JT_EQ_REF || first_inner_tab) { DBUG_EXECUTE("where",print_where(tmp, - tab->table? tab->table->alias.c_ptr() :"sjm-nest", + tab->table ? + tab->table->alias.c_ptr() :"sjm-nest", QT_ORDINARY);); SQL_SELECT *sel= tab->select= ((SQL_SELECT*) thd->memdup((uchar*) select, @@ -14104,10 +14127,12 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) if (tab->bush_root_tab && tab->bush_root_tab->bush_children->start == tab) prev_tab= NULL; - DBUG_ASSERT(tab->bush_children || tab->table == join->best_positions[i].table->table); + DBUG_ASSERT(tab->bush_children || + tab->table == join->best_positions[i].table->table); tab->partial_join_cardinality= join->best_positions[i].records_read * - (prev_tab? prev_tab->partial_join_cardinality : 1); + (prev_tab ? + prev_tab->partial_join_cardinality : 1); if (!tab->bush_children) i++; } @@ -14115,7 +14140,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) check_join_cache_usage_for_tables(join, options, no_jbuf_after); JOIN_TAB *first_tab; - for (tab= first_tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); + for (tab= first_tab= first_linear_tab(join, + WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS)) { @@ -14530,7 +14556,7 @@ double JOIN_TAB::scan_time() if (table->is_filled_at_execution()) { get_delayed_table_estimates(table, &records, &read_time, - &startup_cost); + &startup_cost); found_records= records; table->opt_range_condition_rows= records; } @@ -17887,17 +17913,18 @@ static bool check_interleaving_with_nj(JOIN_TAB *next_tab) Do update counters for "pairs of brackets" that we've left (marked as X,Y,Z in the above picture) */ - for (;next_emb && next_emb != join->emb_sjm_nest; next_emb= next_emb->embedding) + for (;next_emb && next_emb != join->emb_sjm_nest; + next_emb= next_emb->embedding) { if (!next_emb->sj_on_expr) { next_emb->nested_join->counter++; if (next_emb->nested_join->counter == 1) { - /* + /* next_emb is the first table inside a nested join we've "entered". In - the picture above, we're looking at the 'X' bracket. Don't exit yet as - X bracket might have Y pair bracket. + the picture above, we're looking at the 'X' bracket. Don't exit yet + as X bracket might have Y pair bracket. */ join->cur_embedding_map |= next_emb->nested_join->nj_map; } @@ -19911,7 +19938,7 @@ bool Create_tmp_table::finalize(THD *thd, bool save_abort_on_warning; uchar *pos; uchar *null_flags; - KEY *keyinfo; + KEY *keyinfo= param->keyinfo; TMP_ENGINE_COLUMNDEF *recinfo; TABLE_SHARE *share= table->s; Copy_field *copy= param->copy_field; @@ -20103,12 +20130,10 @@ bool Create_tmp_table::finalize(THD *thd, set_if_smaller(share->max_rows, m_rows_limit); param->end_write_records= m_rows_limit; - keyinfo= param->keyinfo; - if (m_group) { DBUG_PRINT("info",("Creating group key in temporary table")); - table->group= m_group; /* Table is grouped by key */ + table->group= m_group; /* Table is grouped by key */ param->group_buff= m_group_buff; share->keys=1; share->uniques= MY_TEST(m_using_unique_constraint); @@ -20118,7 +20143,8 @@ bool Create_tmp_table::finalize(THD *thd, keyinfo->key_part= m_key_part_info; keyinfo->flags=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY; keyinfo->ext_key_flags= keyinfo->flags; - keyinfo->usable_key_parts=keyinfo->user_defined_key_parts= param->group_parts; + keyinfo->usable_key_parts=keyinfo->user_defined_key_parts= + param->group_parts; keyinfo->ext_key_parts= keyinfo->user_defined_key_parts; keyinfo->key_length=0; keyinfo->rec_per_key=NULL; @@ -23748,10 +23774,10 @@ bool test_if_ref(Item *root_cond, Item_field *left_item,Item *right_item) @param cond Condition to analyze @param tables Tables for which "current field values" are available + Tables for which "current field values" are available (this + includes used_table) + (may also include PSEUDO_TABLE_BITS, and may be zero) @param used_table Table that we're extracting the condition for - tables Tables for which "current field values" are available (this - includes used_table) - (may also include PSEUDO_TABLE_BITS, and may be zero) @param join_tab_idx_arg The index of the JOIN_TAB this Item is being extracted for. MAX_TABLES if there is no corresponding JOIN_TAB. @@ -27788,7 +27814,7 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tables, bool distinct_arg, JOIN_TAB *first_top_tab) { - int quick_type; + int quick_type= -1; CHARSET_INFO *cs= system_charset_info; THD *thd= join->thd; TABLE_LIST *table_list= table->pos_in_table_list; @@ -27797,7 +27823,6 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta, char table_name_buffer[SAFE_NAME_LEN]; KEY *key_info= 0; uint key_len= 0; - quick_type= -1; explain_plan= eta; eta->key.clear(); @@ -29351,8 +29376,8 @@ void JOIN::restore_query_plan(Join_plan_state *restore_from) @param added_where An extra conjunct to the WHERE clause to reoptimize with @param join_tables The set of tables to reoptimize - @param save_to If != NULL, save here the state of the current query plan, - otherwise reuse the existing query plan structures. + @param save_to If != NULL, save here the state of the current query + plan, otherwise reuse the existing query plan structures. @notes Given a query plan that was already optimized taking into account some WHERE @@ -29369,7 +29394,8 @@ void JOIN::restore_query_plan(Join_plan_state *restore_from) @retval REOPT_NEW_PLAN there is a new plan. @retval REOPT_OLD_PLAN no new improved plan was produced, use the old one. - @retval REOPT_ERROR an irrecovarable error occurred during reoptimization. + @retval REOPT_ERROR an irrecovarable error occurred during + reoptimization. */ JOIN::enum_reopt_result @@ -29381,8 +29407,8 @@ JOIN::reoptimize(Item *added_where, table_map join_tables, size_t 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, table_count, added_where, - ~outer_join, select_lex, &sargables)) + if (update_ref_and_keys(thd, &added_keyuse, join_tab, table_count, + added_where, ~outer_join, select_lex, &sargables)) { delete_dynamic(&added_keyuse); return REOPT_ERROR; @@ -30062,7 +30088,7 @@ uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, if (select && select->quick) return select->quick->index; // index or MAX_KEY, use quick select as is else - return table->file->key_used_on_scan; // MAX_KEY or index for some engines + return table->file->key_used_on_scan; // MAX_KEY or index for some engine } if (!is_simple_order(order)) // just to cut further expensive checks @@ -30110,11 +30136,13 @@ uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, DBUG_ASSERT(0); } else if (limit != HA_POS_ERROR) - { // check if some index scan & LIMIT is more efficient than filesort + { + // check if some index scan & LIMIT is more efficient than filesort /* - Update opt_range_condition_rows since single table UPDATE/DELETE procedures - don't call make_join_statistics() and leave this variable uninitialized. + Update opt_range_condition_rows since single table UPDATE/DELETE + procedures don't call make_join_statistics() and leave this + variable uninitialized. */ table->opt_range_condition_rows= table->stat_records(); @@ -30692,20 +30720,22 @@ bool build_notnull_conds_for_range_scans(JOIN *join, Item *cond, @brief Build not null conditions for inner nest tables of an outer join - @param join the join for whose table nest not null conditions are to be built + @param join the join for whose table nest not null conditions are to be + built @param nest_tbl the nest of the inner tables of an outer join @details - The function assumes that nest_tbl is the nest of the inner tables of an - outer join and so an ON expression for this outer join is attached to - nest_tbl. - The function selects the tables of the nest_tbl that are not inner tables of - embedded outer joins and then it calls build_notnull_conds_for_range_scans() - for nest_tbl->on_expr and the bitmap for the selected tables. This call - finds all fields belonging to the selected tables whose null-rejectedness - can be inferred from the null-rejectedness of nest_tbl->on_expr. After this - the function recursively finds all null_rejected fields for the remaining - tables from the nest of nest_tbl. + The function assumes that nest_tbl is the nest of the inner tables + of an outer join and so an ON expression for this outer join is + attached to nest_tbl. + The function selects the tables of the nest_tbl that are not inner + tables of embedded outer joins and then it calls + build_notnull_conds_for_range_scans() for nest_tbl->on_expr and + the bitmap for the selected tables. This call finds all fields + belonging to the selected tables whose null-rejectedness can be + inferred from the null-rejectedness of nest_tbl->on_expr. After + this the function recursively finds all null_rejected fields for + the remaining tables from the nest of nest_tbl. */ static diff --git a/sql/sql_select.h b/sql/sql_select.h index fa4d373d556..819e9d1968f 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1343,7 +1343,9 @@ public: int dbug_join_tab_array_size; #endif - /* We also maintain a stack of join optimization states in * join->positions[] */ + /* + We also maintain a stack of join optimization states in join->positions[] + */ /******* Join optimization state members end *******/ /* diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f56ec5c83c9..2da95904419 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -833,9 +833,9 @@ int mysql_update(THD *thd, table->use_all_columns(); /* - We are doing a search on a key that is updated. In this case - we go trough the matching rows, save a pointer to them and - update these in a separate loop based on the pointer. + We are doing a search on a key that is updated. In this case + we go trough the matching rows, save a pointer to them and + update these in a separate loop based on the pointer. */ explain->buf_tracker.on_scan_init(); IO_CACHE tempfile;