diff options
Diffstat (limited to 'sql/sql_statistics.cc')
-rw-r--r-- | sql/sql_statistics.cc | 85 |
1 files changed, 54 insertions, 31 deletions
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 11e2db9ae44..f8723a4f8ee 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -28,6 +28,7 @@ #include "key.h" #include "sql_statistics.h" #include "opt_range.h" +#include "uniques.h" #include "my_atomic.h" #include "sql_show.h" #include "sql_partition.h" @@ -843,7 +844,7 @@ public: else { stat_field->set_notnull(); - stat_field->store(table->collected_stats->cardinality); + stat_field->store(table->collected_stats->cardinality,true); } } @@ -1043,6 +1044,9 @@ public: { char buff[MAX_FIELD_WIDTH]; String val(buff, sizeof(buff), &my_charset_bin); + my_bitmap_map *old_map; + + old_map= dbug_tmp_use_all_columns(stat_table, stat_table->read_set); for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++) { @@ -1055,20 +1059,24 @@ public: switch (i) { case COLUMN_STAT_MIN_VALUE: if (table_field->type() == MYSQL_TYPE_BIT) - stat_field->store(table_field->collected_stats->min_value->val_int()); + stat_field->store(table_field->collected_stats->min_value->val_int(),true); else { table_field->collected_stats->min_value->val_str(&val); - stat_field->store(val.ptr(), val.length(), &my_charset_bin); + uint32 length= Well_formed_prefix(val.charset(), val.ptr(), + MY_MIN(val.length(), stat_field->field_length)).length(); + stat_field->store(val.ptr(), length, &my_charset_bin); } break; case COLUMN_STAT_MAX_VALUE: if (table_field->type() == MYSQL_TYPE_BIT) - stat_field->store(table_field->collected_stats->max_value->val_int()); + stat_field->store(table_field->collected_stats->max_value->val_int(),true); else { table_field->collected_stats->max_value->val_str(&val); - stat_field->store(val.ptr(), val.length(), &my_charset_bin); + uint32 length= Well_formed_prefix(val.charset(), val.ptr(), + MY_MIN(val.length(), stat_field->field_length)).length(); + stat_field->store(val.ptr(), length, &my_charset_bin); } break; case COLUMN_STAT_NULLS_RATIO: @@ -1097,6 +1105,7 @@ public: } } } + dbug_tmp_restore_column_map(stat_table->read_set, old_map); } @@ -1632,7 +1641,7 @@ public: of the parameters to be passed to the constructor of the Unique object. */ - Count_distinct_field(Field *field, uint max_heap_table_size) + Count_distinct_field(Field *field, size_t max_heap_table_size) { table_field= field; tree_key_length= field->pack_length(); @@ -1730,7 +1739,7 @@ class Count_distinct_field_bit: public Count_distinct_field { public: - Count_distinct_field_bit(Field *field, uint max_heap_table_size) + Count_distinct_field_bit(Field *field, size_t max_heap_table_size) { table_field= field; tree_key_length= sizeof(ulonglong); @@ -1802,18 +1811,16 @@ private: public: bool is_single_comp_pk; + bool is_partial_fields_present; - Index_prefix_calc(TABLE *table, KEY *key_info) - : index_table(table), index_info(key_info) + Index_prefix_calc(THD *thd, TABLE *table, KEY *key_info) + : index_table(table), index_info(key_info), prefixes(0), empty(true), + calc_state(NULL), is_single_comp_pk(false), is_partial_fields_present(false) { uint i; Prefix_calc_state *state; uint key_parts= table->actual_n_key_parts(key_info); - empty= TRUE; - prefixes= 0; - LINT_INIT_STRUCT(calc_state); - is_single_comp_pk= FALSE; uint pk= table->s->primary_key; if ((uint) (table->key_info - key_info) == pk && table->key_info[pk].user_defined_key_parts == 1) @@ -1824,9 +1831,9 @@ public: } if ((calc_state= - (Prefix_calc_state *) sql_alloc(sizeof(Prefix_calc_state)*key_parts))) + (Prefix_calc_state *) thd->alloc(sizeof(Prefix_calc_state)*key_parts))) { - uint keyno= key_info-table->key_info; + uint keyno= (uint)(key_info-table->key_info); for (i= 0, state= calc_state; i < key_parts; i++, state++) { /* @@ -1835,10 +1842,14 @@ public: calculating the values of 'avg_frequency' for prefixes. */ if (!key_info->key_part[i].field->part_of_key.is_set(keyno)) + { + is_partial_fields_present= TRUE; break; + } if (!(state->last_prefix= - new Cached_item_field(key_info->key_part[i].field))) + new (thd->mem_root) Cached_item_field(thd, + key_info->key_part[i].field))) break; state->entry_count= state->prefix_count= 0; prefixes++; @@ -1968,7 +1979,7 @@ void create_min_max_statistical_fields_for_table(TABLE *table) my_ptrdiff_t diff= record-table->record[0]; if (!bitmap_is_set(table->read_set, table_field->field_index)) continue; - if (!(fld= table_field->clone(&table->mem_root, table, diff, TRUE))) + if (!(fld= table_field->clone(&table->mem_root, table, diff))) continue; if (i == 0) table_field->collected_stats->min_value= fld; @@ -2035,7 +2046,7 @@ void create_min_max_statistical_fields_for_table_share(THD *thd, Field *fld; Field *table_field= *field_ptr; my_ptrdiff_t diff= record - table_share->default_values; - if (!(fld= table_field->clone(&stats_cb->mem_root, diff))) + if (!(fld= table_field->clone(&stats_cb->mem_root, NULL, diff))) continue; if (i == 0) table_field->read_stats->min_value= fld; @@ -2385,7 +2396,7 @@ int alloc_histograms_for_table_share(THD* thd, TABLE_SHARE *table_share, inline void Column_statistics_collected::init(THD *thd, Field *table_field) { - uint max_heap_table_size= thd->variables.max_heap_table_size; + size_t max_heap_table_size= (size_t)thd->variables.max_heap_table_size; TABLE *table= table_field->table; uint pk= table->s->primary_key; @@ -2568,7 +2579,7 @@ int collect_statistics_for_index(THD *thd, TABLE *table, uint index) if (key_info->flags & (HA_FULLTEXT|HA_SPATIAL)) DBUG_RETURN(rc); - Index_prefix_calc index_prefix_calc(table, key_info); + Index_prefix_calc index_prefix_calc(thd, table, key_info); DEBUG_SYNC(table->in_use, "statistics_collection_start1"); DEBUG_SYNC(table->in_use, "statistics_collection_start2"); @@ -2579,9 +2590,13 @@ int collect_statistics_for_index(THD *thd, TABLE *table, uint index) DBUG_RETURN(rc); } - table->key_read= 1; - table->file->extra(HA_EXTRA_KEYREAD); - + /* + Request "only index read" in case of absence of fields which are + partially in the index to avoid problems with partitioning (for example) + which want to get whole field value. + */ + if (!index_prefix_calc.is_partial_fields_present) + table->file->ha_start_keyread(index); table->file->ha_index_init(index, TRUE); rc= table->file->ha_index_first(table->record[0]); while (rc != HA_ERR_END_OF_FILE) @@ -2595,7 +2610,7 @@ int collect_statistics_for_index(THD *thd, TABLE *table, uint index) index_prefix_calc.add(); rc= table->file->ha_index_next(table->record[0]); } - table->key_read= 0; + table->file->ha_end_keyread(); table->file->ha_index_end(); rc= (rc == HA_ERR_END_OF_FILE && !thd->killed) ? 0 : 1; @@ -2914,9 +2929,13 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) KEY *key_info, *key_info_end; TABLE_SHARE *table_share= table->s; Table_statistics *read_stats= table_share->stats_cb.table_stats; + enum_check_fields old_check_level= thd->count_cuted_fields; DBUG_ENTER("read_statistics_for_table"); + /* Don't write warnings for internal field conversions */ + thd->count_cuted_fields= CHECK_FIELD_IGNORE; + /* Read statistics from the statistical table table_stats */ stat_table= stat_tables[TABLE_STAT].table; Table_stat table_stat(stat_table, table); @@ -2995,8 +3014,9 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) } } } - + table->stats_is_read= TRUE; + thd->count_cuted_fields= old_check_level; DBUG_RETURN(0); } @@ -3770,14 +3790,14 @@ double get_column_avg_frequency(Field * field) */ if (!table->s->field) { - res= table->stat_records(); + res= (double)table->stat_records(); return res; } - Column_statistics *col_stats= table->s->field[field->field_index]->read_stats; + Column_statistics *col_stats= field->read_stats; if (!col_stats) - res= table->stat_records(); + res= (double)table->stat_records(); else res= col_stats->get_avg_frequency(); return res; @@ -3802,7 +3822,10 @@ double get_column_avg_frequency(Field * field) using the statistical data from the table column_stats. @retval - The required estimate of the rows in the column range + - The required estimate of the rows in the column range + - If there is some kind of error, this function should return DBL_MAX (and + not HA_POS_ERROR as that is an integer constant). + */ double get_column_range_cardinality(Field *field, @@ -3812,8 +3835,8 @@ double get_column_range_cardinality(Field *field, { double res; TABLE *table= field->table; - Column_statistics *col_stats= table->field[field->field_index]->read_stats; - double tab_records= table->stat_records(); + Column_statistics *col_stats= field->read_stats; + double tab_records= (double)table->stat_records(); if (!col_stats) return tab_records; |