diff options
author | Igor Babaev <igor@askmonty.org> | 2012-09-08 12:04:31 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-09-08 12:04:31 -0700 |
commit | b3f09e8aa04aa3d2d2b86588eddd46badb7e916f (patch) | |
tree | 959358cacf51917fbb7a85cde033d9cb3d2fb45a /sql | |
parent | cfde11fc4f02e701b856311769d70ccc47d16539 (diff) | |
download | mariadb-git-b3f09e8aa04aa3d2d2b86588eddd46badb7e916f.tar.gz |
Fixed bug mdev-504.
Opening system statistical tables and reading statistical data from
them for a regular table should be done after opening and locking
this regular table.
No test case is provided with this patch.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_base.cc | 10 | ||||
-rw-r--r-- | sql/sql_base.h | 2 | ||||
-rw-r--r-- | sql/sql_statistics.cc | 156 |
3 files changed, 136 insertions, 32 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 691add25497..f3e180553f0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4665,13 +4665,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables, (*table_field_ptr)->read_stats= (*field_ptr)->read_stats; table_share->stats_can_be_read= TRUE; - } - - if (table_share->stats_can_be_read && !table_share->stats_is_read) - { - (void) read_statistics_for_table(thd, tables->table); - table_share->stats_is_read= TRUE; - } + } } } @@ -5615,6 +5609,8 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables, if (lock_tables(thd, tables, counter, flags)) goto err; + (void) read_statistics_for_tables_if_needed(thd, tables); + if (derived) { if (mysql_handle_derived(thd->lex, DT_INIT)) diff --git a/sql/sql_base.h b/sql/sql_base.h index a8d4951981e..698c4a012e7 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -312,7 +312,7 @@ int dynamic_column_error_message(enum_dyncol_func_result rc); /* open_and_lock_tables with optional derived handling */ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived); -int read_statistics_for_table(THD *thd, TABLE *table); +int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables); int collect_statistics_for_table(THD *thd, TABLE *table); int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *share, bool is_safe); diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index c3d95da007e..56db95d40b5 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -1726,7 +1726,7 @@ int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share, Field **field_ptr; uint cnt= 0; - DBUG_ENTER("alloc_statistics_for_table"); + DBUG_ENTER("alloc_statistics_for_table_share"); DEBUG_SYNC(thd, "statistics_mem_alloc_start1"); DEBUG_SYNC(thd, "statistics_mem_alloc_start2"); @@ -2245,6 +2245,8 @@ int update_statistics_for_table(THD *thd, TABLE *table) thd The thread handle @param table The table to read statistics on + @param + stat_tables The array of TABLE_LIST objects for statistical tables @details For each statistical table the function looks for the rows from this @@ -2252,54 +2254,42 @@ int update_statistics_for_table(THD *thd, TABLE *table) the data from statistical columns of it is read into the appropriate fields of internal structures for 'table'. Later at the query processing this data are supposed to be used by the optimizer. - The function is called in function open_tables. + The parameter stat_tables should point to an array of TABLE_LIST + objects for all statistical tables linked into a list. All statistical + tables are supposed to be opened. + The function is called by read_statistics_for_table_if_needed(). @retval - 0 If data has been successfully read from all statistical tables + 0 If data has been successfully read for the table @retval 1 Otherwise @note - The function first calls the function open_system_tables_for_read to - be able to read info from the statistical tables. On success the data is - read from one table after another after which the statistical tables are - closed. Objects of the helper classes Table_stat, Column_stat and Index_stat + Objects of the helper classes Table_stat, Column_stat and Index_stat are employed to read statistical data from the statistical tables. - TODO. Consider a variant when statistical tables are opened and closed - only once for all tables, not for every table of the query as it's done now. */ -int read_statistics_for_table(THD *thd, TABLE *table) +static +int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) { uint i; TABLE *stat_table; Field *table_field; Field **field_ptr; KEY *key_info, *key_info_end; - TABLE_LIST tables[STATISTICS_TABLES]; - Open_tables_backup open_tables_backup; TABLE_SHARE *table_share= table->s; DBUG_ENTER("read_statistics_for_table"); - init_table_list_for_stat_tables(tables, FALSE); - init_mdl_requests(tables); - - if (open_system_tables_for_read(thd, tables, &open_tables_backup)) - { - thd->clear_error(); - DBUG_RETURN(0); - } - /* Read statistics from the statistical table table_stat */ - stat_table= tables[TABLE_STAT].table; + stat_table= stat_tables[TABLE_STAT].table; Table_stat table_stat(stat_table, table); table_stat.set_key_fields(); table_stat.get_stat_values(); /* Read statistics from the statistical table column_stat */ - stat_table= tables[COLUMN_STAT].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++) { @@ -2309,7 +2299,7 @@ int read_statistics_for_table(THD *thd, TABLE *table) } /* Read statistics from the statistical table index_stat */ - stat_table= tables[INDEX_STAT].table; + stat_table= stat_tables[INDEX_STAT].table; Index_stat index_stat(stat_table, table); for (key_info= table_share->key_info, key_info_end= key_info + table_share->keys; @@ -2369,6 +2359,124 @@ int read_statistics_for_table(THD *thd, TABLE *table) } } + DBUG_RETURN(0); +} + + +/** + @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 (thd->bootstrap || thd->variables.use_stat_tables == 0) + return FALSE; + + if (!tables) + return FALSE; + + switch(thd->lex->sql_command) { + case SQLCOM_SELECT: + case SQLCOM_INSERT: + case SQLCOM_INSERT_SELECT: + case SQLCOM_UPDATE: + case SQLCOM_UPDATE_MULTI: + case SQLCOM_DELETE: + case SQLCOM_DELETE_MULTI: + case SQLCOM_REPLACE: + case SQLCOM_REPLACE_SELECT: + break; + default: + return FALSE; + } + + for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) + { + if (!tl->is_view_or_derived() && tl->table) + { + TABLE_SHARE *table_share= tl->table->s; + if (table_share && + table_share->stats_can_be_read && + !table_share->stats_is_read) + return TRUE; + } + } + + return FALSE; +} + + +/** + @brief + Read statistics for tables from a table list if it is needed + + @param + thd The thread handle + @param + tables The tables list for whose tables to read statistics + + @details + The function first checks whether for any of the tables opened and locked + for a statement statistics from statistical tables is needed to be read. + Then, if so, it opens system statistical tables for read and reads + the statistical data from them for those tables from the list for which it + makes sense. Then the function closes system statistical tables. + + @retval + 0 Statistics for tables was successfully read + @retval + 1 Otherwise +*/ + +int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables) +{ + TABLE_LIST stat_tables[STATISTICS_TABLES]; + Open_tables_backup open_tables_backup; + + DBUG_ENTER("read_statistics_for_table_if_needed"); + + if (!statistics_for_tables_is_needed(thd, tables)) + DBUG_RETURN(0); + + init_table_list_for_stat_tables(stat_tables, FALSE); + init_mdl_requests(stat_tables); + if (open_system_tables_for_read(thd, stat_tables, &open_tables_backup)) + { + thd->clear_error(); + DBUG_RETURN(1); + } + + for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) + { + if (!tl->is_view_or_derived() && tl->table) + { + TABLE_SHARE *table_share= tl->table->s; + if (table_share && + table_share->stats_can_be_read && + !table_share->stats_is_read) + { + (void) read_statistics_for_table(thd, tl->table, stat_tables); + table_share->stats_is_read= TRUE; + } + } + } + close_system_tables(thd, &open_tables_backup); DBUG_RETURN(0); |