mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge 10.1 into 10.2
This commit is contained in:
@ -2216,27 +2216,13 @@ static int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share)
|
||||
|
||||
DBUG_ENTER("alloc_statistics_for_table_share");
|
||||
|
||||
DEBUG_SYNC(thd, "statistics_mem_alloc_start1");
|
||||
DEBUG_SYNC(thd, "statistics_mem_alloc_start2");
|
||||
|
||||
mysql_mutex_lock(&table_share->LOCK_share);
|
||||
|
||||
if (stats_cb->stats_can_be_read)
|
||||
{
|
||||
mysql_mutex_unlock(&table_share->LOCK_share);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
Table_statistics *table_stats= stats_cb->table_stats;
|
||||
if (!table_stats)
|
||||
{
|
||||
table_stats= (Table_statistics *) alloc_root(&stats_cb->mem_root,
|
||||
sizeof(Table_statistics));
|
||||
if (!table_stats)
|
||||
{
|
||||
mysql_mutex_unlock(&table_share->LOCK_share);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
memset(table_stats, 0, sizeof(Table_statistics));
|
||||
stats_cb->table_stats= table_stats;
|
||||
}
|
||||
@ -2302,88 +2288,10 @@ static int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (column_stats && index_stats && idx_avg_frequency)
|
||||
stats_cb->stats_can_be_read= TRUE;
|
||||
|
||||
mysql_mutex_unlock(&table_share->LOCK_share);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(column_stats && index_stats && idx_avg_frequency ? 0 : 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief
|
||||
Allocate memory for the histogram used by a table share
|
||||
|
||||
@param
|
||||
thd Thread handler
|
||||
@param
|
||||
table_share Table share for which the memory for histogram data is allocated
|
||||
@param
|
||||
is_safe TRUE <-> at any time only one thread can perform the function
|
||||
|
||||
@note
|
||||
The function allocates the memory for the histogram built for a table in the
|
||||
table's share memory with the intention to read the data there from the
|
||||
system persistent statistical table mysql.column_stats,
|
||||
The memory is allocated in the table_share's mem_root.
|
||||
If the parameter is_safe is TRUE then it is guaranteed that at any given time
|
||||
only one thread is executed the code of the function.
|
||||
|
||||
@retval
|
||||
0 If the memory for all statistical data has been successfully allocated
|
||||
@retval
|
||||
1 Otherwise
|
||||
|
||||
@note
|
||||
Currently the function always is called with the parameter is_safe set
|
||||
to FALSE.
|
||||
*/
|
||||
|
||||
static
|
||||
int alloc_histograms_for_table_share(THD* thd, TABLE_SHARE *table_share,
|
||||
bool is_safe)
|
||||
{
|
||||
TABLE_STATISTICS_CB *stats_cb= &table_share->stats_cb;
|
||||
|
||||
DBUG_ENTER("alloc_histograms_for_table_share");
|
||||
|
||||
if (!is_safe)
|
||||
mysql_mutex_lock(&table_share->LOCK_share);
|
||||
|
||||
if (stats_cb->histograms_can_be_read)
|
||||
{
|
||||
if (!is_safe)
|
||||
mysql_mutex_unlock(&table_share->LOCK_share);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
Table_statistics *table_stats= stats_cb->table_stats;
|
||||
ulong total_hist_size= table_stats->total_hist_size;
|
||||
|
||||
if (total_hist_size && !table_stats->histograms)
|
||||
{
|
||||
uchar *histograms= (uchar *) alloc_root(&stats_cb->mem_root,
|
||||
total_hist_size);
|
||||
if (!histograms)
|
||||
{
|
||||
if (!is_safe)
|
||||
mysql_mutex_unlock(&table_share->LOCK_share);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
memset(histograms, 0, total_hist_size);
|
||||
table_stats->histograms= histograms;
|
||||
stats_cb->histograms_can_be_read= TRUE;
|
||||
}
|
||||
|
||||
if (!is_safe)
|
||||
mysql_mutex_unlock(&table_share->LOCK_share);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@brief
|
||||
Initialize the aggregation fields to collect statistics on a column
|
||||
@ -2929,15 +2837,26 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
|
||||
Field **field_ptr;
|
||||
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");
|
||||
DEBUG_SYNC(thd, "statistics_mem_alloc_start1");
|
||||
DEBUG_SYNC(thd, "statistics_mem_alloc_start2");
|
||||
|
||||
if (!table_share->stats_cb.start_stats_load())
|
||||
DBUG_RETURN(table_share->stats_cb.stats_are_ready() ? 0 : 1);
|
||||
|
||||
if (alloc_statistics_for_table_share(thd, table_share))
|
||||
{
|
||||
table_share->stats_cb.abort_stats_load();
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/* Don't write warnings for internal field conversions */
|
||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
|
||||
|
||||
/* Read statistics from the statistical table table_stats */
|
||||
Table_statistics *read_stats= table_share->stats_cb.table_stats;
|
||||
stat_table= stat_tables[TABLE_STAT].table;
|
||||
Table_stat table_stat(stat_table, table);
|
||||
table_stat.set_key_fields();
|
||||
@ -2954,7 +2873,7 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
|
||||
column_stat.get_stat_values();
|
||||
total_hist_size+= table_field->read_stats->histogram.get_size();
|
||||
}
|
||||
read_stats->total_hist_size= total_hist_size;
|
||||
table_share->stats_cb.total_hist_size= total_hist_size;
|
||||
|
||||
/* Read statistics from the statistical table index_stats */
|
||||
stat_table= stat_tables[INDEX_STAT].table;
|
||||
@ -3016,9 +2935,8 @@ 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;
|
||||
|
||||
table_share->stats_cb.end_stats_load();
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -3056,71 +2974,6 @@ void delete_stat_values_for_table_share(TABLE_SHARE *table_share)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief
|
||||
Check whether any statistics is to be read for tables from a table list
|
||||
|
||||
@param
|
||||
thd The thread handle
|
||||
@param
|
||||
tables The tables list for whose tables the check is to be done
|
||||
|
||||
@details
|
||||
The function checks whether for any of the tables opened and locked for
|
||||
a statement statistics from statistical tables is needed to be read.
|
||||
|
||||
@retval
|
||||
TRUE statistics for any of the tables is needed to be read
|
||||
@retval
|
||||
FALSE Otherwise
|
||||
*/
|
||||
|
||||
static
|
||||
bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
|
||||
{
|
||||
if (!tables)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
Do not read statistics for any query that explicity involves
|
||||
statistical tables, failure to to do so we may end up
|
||||
in a deadlock.
|
||||
*/
|
||||
|
||||
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
|
||||
{
|
||||
if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
|
||||
{
|
||||
TABLE_SHARE *table_share= tl->table->s;
|
||||
if (table_share &&
|
||||
table_share->table_category != TABLE_CATEGORY_USER
|
||||
&& is_stat_table(tl->db, tl->alias))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
|
||||
{
|
||||
if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
|
||||
{
|
||||
TABLE_SHARE *table_share= tl->table->s;
|
||||
if (table_share &&
|
||||
table_share->stats_cb.stats_can_be_read &&
|
||||
(!table_share->stats_cb.stats_is_read ||
|
||||
(!table_share->stats_cb.histograms_are_read &&
|
||||
thd->variables.optimizer_use_condition_selectivity > 3)))
|
||||
return TRUE;
|
||||
if (table_share->stats_cb.stats_is_read)
|
||||
tl->table->stats_is_read= TRUE;
|
||||
if (table_share->stats_cb.histograms_are_read)
|
||||
tl->table->histograms_are_read= TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief
|
||||
Read histogram for a table from the persistent statistical tables
|
||||
@ -3156,26 +3009,25 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
|
||||
static
|
||||
int read_histograms_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
|
||||
{
|
||||
TABLE_SHARE *table_share= table->s;
|
||||
|
||||
TABLE_STATISTICS_CB *stats_cb= &table->s->stats_cb;
|
||||
DBUG_ENTER("read_histograms_for_table");
|
||||
|
||||
if (!table_share->stats_cb.histograms_can_be_read)
|
||||
if (stats_cb->start_histograms_load())
|
||||
{
|
||||
(void) alloc_histograms_for_table_share(thd, table_share, FALSE);
|
||||
}
|
||||
if (table_share->stats_cb.histograms_can_be_read &&
|
||||
!table_share->stats_cb.histograms_are_read)
|
||||
{
|
||||
Field **field_ptr;
|
||||
uchar *histogram= table_share->stats_cb.table_stats->histograms;
|
||||
TABLE *stat_table= stat_tables[COLUMN_STAT].table;
|
||||
Column_stat column_stat(stat_table, table);
|
||||
for (field_ptr= table_share->field; *field_ptr; field_ptr++)
|
||||
uchar *histogram= (uchar *) alloc_root(&stats_cb->mem_root,
|
||||
stats_cb->total_hist_size);
|
||||
if (!histogram)
|
||||
{
|
||||
stats_cb->abort_histograms_load();
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
memset(histogram, 0, stats_cb->total_hist_size);
|
||||
|
||||
Column_stat column_stat(stat_tables[COLUMN_STAT].table, table);
|
||||
for (Field **field_ptr= table->s->field; *field_ptr; field_ptr++)
|
||||
{
|
||||
Field *table_field= *field_ptr;
|
||||
uint hist_size= table_field->read_stats->histogram.get_size();
|
||||
if (hist_size)
|
||||
if (uint hist_size= table_field->read_stats->histogram.get_size())
|
||||
{
|
||||
column_stat.set_key_fields(table_field);
|
||||
table_field->read_stats->histogram.set_values(histogram);
|
||||
@ -3183,8 +3035,9 @@ int read_histograms_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
|
||||
histogram+= hist_size;
|
||||
}
|
||||
}
|
||||
stats_cb->end_histograms_load();
|
||||
}
|
||||
|
||||
table->histograms_are_read= true;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -3232,6 +3085,23 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
|
||||
}
|
||||
|
||||
|
||||
static void dump_stats_from_share_to_table(TABLE *table)
|
||||
{
|
||||
TABLE_SHARE *table_share= table->s;
|
||||
KEY *key_info= table_share->key_info;
|
||||
KEY *key_info_end= key_info + table_share->keys;
|
||||
KEY *table_key_info= table->key_info;
|
||||
for ( ; key_info < key_info_end; key_info++, table_key_info++)
|
||||
table_key_info->read_stats= key_info->read_stats;
|
||||
|
||||
Field **field_ptr= table_share->field;
|
||||
Field **table_field_ptr= table->field;
|
||||
for ( ; *field_ptr; field_ptr++, table_field_ptr++)
|
||||
(*table_field_ptr)->read_stats= (*field_ptr)->read_stats;
|
||||
table->stats_is_read= true;
|
||||
}
|
||||
|
||||
|
||||
int read_statistics_for_tables(THD *thd, TABLE_LIST *tables)
|
||||
{
|
||||
TABLE_LIST stat_tables[STATISTICS_TABLES];
|
||||
@ -3242,38 +3112,42 @@ int read_statistics_for_tables(THD *thd, TABLE_LIST *tables)
|
||||
if (thd->bootstrap || thd->variables.use_stat_tables == NEVER)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
bool found_stat_table= false;
|
||||
bool statistics_for_tables_is_needed= false;
|
||||
|
||||
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
|
||||
{
|
||||
if (tl->table)
|
||||
TABLE_SHARE *table_share;
|
||||
if (!tl->is_view_or_derived() && tl->table && (table_share= tl->table->s) &&
|
||||
table_share->tmp_table == NO_TMP_TABLE)
|
||||
{
|
||||
TABLE_SHARE *table_share= tl->table->s;
|
||||
if (table_share && table_share->table_category == TABLE_CATEGORY_USER &&
|
||||
table_share->tmp_table == NO_TMP_TABLE)
|
||||
if (table_share->table_category == TABLE_CATEGORY_USER)
|
||||
{
|
||||
if (table_share->stats_cb.stats_can_be_read ||
|
||||
!alloc_statistics_for_table_share(thd, table_share))
|
||||
if (table_share->stats_cb.stats_are_ready())
|
||||
{
|
||||
if (table_share->stats_cb.stats_can_be_read)
|
||||
{
|
||||
KEY *key_info= table_share->key_info;
|
||||
KEY *key_info_end= key_info + table_share->keys;
|
||||
KEY *table_key_info= tl->table->key_info;
|
||||
for ( ; key_info < key_info_end; key_info++, table_key_info++)
|
||||
table_key_info->read_stats= key_info->read_stats;
|
||||
Field **field_ptr= table_share->field;
|
||||
Field **table_field_ptr= tl->table->field;
|
||||
for ( ; *field_ptr; field_ptr++, table_field_ptr++)
|
||||
(*table_field_ptr)->read_stats= (*field_ptr)->read_stats;
|
||||
tl->table->stats_is_read= table_share->stats_cb.stats_is_read;
|
||||
}
|
||||
if (!tl->table->stats_is_read)
|
||||
dump_stats_from_share_to_table(tl->table);
|
||||
tl->table->histograms_are_read=
|
||||
table_share->stats_cb.histograms_are_ready();
|
||||
if (table_share->stats_cb.histograms_are_ready() ||
|
||||
thd->variables.optimizer_use_condition_selectivity <= 3)
|
||||
continue;
|
||||
}
|
||||
statistics_for_tables_is_needed= true;
|
||||
}
|
||||
else if (is_stat_table(tl->db, tl->alias))
|
||||
found_stat_table= true;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_SYNC(thd, "statistics_read_start");
|
||||
|
||||
if (!statistics_for_tables_is_needed(thd, tables))
|
||||
/*
|
||||
Do not read statistics for any query that explicity involves
|
||||
statistical tables, failure to to do so we may end up
|
||||
in a deadlock.
|
||||
*/
|
||||
if (found_stat_table || !statistics_for_tables_is_needed)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
if (open_stat_tables(thd, stat_tables, &open_tables_backup, FALSE))
|
||||
@ -3281,32 +3155,22 @@ int read_statistics_for_tables(THD *thd, TABLE_LIST *tables)
|
||||
|
||||
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
|
||||
{
|
||||
if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
|
||||
{
|
||||
TABLE_SHARE *table_share= tl->table->s;
|
||||
if (table_share && !(table_share->table_category == TABLE_CATEGORY_USER))
|
||||
continue;
|
||||
|
||||
if (table_share &&
|
||||
table_share->stats_cb.stats_can_be_read &&
|
||||
!table_share->stats_cb.stats_is_read)
|
||||
TABLE_SHARE *table_share;
|
||||
if (!tl->is_view_or_derived() && tl->table && (table_share= tl->table->s) &&
|
||||
table_share->tmp_table == NO_TMP_TABLE &&
|
||||
table_share->table_category == TABLE_CATEGORY_USER)
|
||||
{
|
||||
if (!tl->table->stats_is_read)
|
||||
{
|
||||
(void) read_statistics_for_table(thd, tl->table, stat_tables);
|
||||
table_share->stats_cb.stats_is_read= TRUE;
|
||||
if (!read_statistics_for_table(thd, tl->table, stat_tables))
|
||||
dump_stats_from_share_to_table(tl->table);
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if (table_share->stats_cb.stats_is_read)
|
||||
tl->table->stats_is_read= TRUE;
|
||||
if (thd->variables.optimizer_use_condition_selectivity > 3 &&
|
||||
table_share && table_share->stats_cb.stats_can_be_read &&
|
||||
!table_share->stats_cb.histograms_are_read)
|
||||
{
|
||||
if (thd->variables.optimizer_use_condition_selectivity > 3)
|
||||
(void) read_histograms_for_table(thd, tl->table, stat_tables);
|
||||
table_share->stats_cb.histograms_are_read= TRUE;
|
||||
}
|
||||
if (table_share->stats_cb.histograms_are_read)
|
||||
tl->table->histograms_are_read= TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close_system_tables(thd, &open_tables_backup);
|
||||
|
||||
|
Reference in New Issue
Block a user