summaryrefslogtreecommitdiff
path: root/sql/sql_statistics.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_statistics.cc')
-rw-r--r--sql/sql_statistics.cc85
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;