From f009c4da915888e0211447bbedb7e3640ec80935 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 1 Sep 2023 11:24:42 +0300 Subject: [PATCH] Small corrections to MDEV-29693 ANALYZE TABLE 32 bit MariaDB crashed in innodb.innodb-16k and a few other tests. Fixed by using correct sizeof() calls. Histograms where not read if first read was without histograms. --- mysql-test/main/stat_tables_flush.result | 73 +++++++++++++++++++++++- mysql-test/main/stat_tables_flush.test | 24 +++++++- sql/sql_statistics.cc | 20 +++++-- sql/table.cc | 16 ++++++ sql/table.h | 1 + 5 files changed, 127 insertions(+), 7 deletions(-) diff --git a/mysql-test/main/stat_tables_flush.result b/mysql-test/main/stat_tables_flush.result index 9a88d5d388d..7c1fdc34e64 100644 --- a/mysql-test/main/stat_tables_flush.result +++ b/mysql-test/main/stat_tables_flush.result @@ -87,5 +87,76 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK drop table t1; # -# End of 10.5 tests +# Test that histograms are read after flush +# +create table t1 (a int); +insert into t1 select seq from seq_1_to_10; +insert into t1 select A.seq from seq_10_to_20 A, seq_1_to_9 B; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +explain format=json select * from t1 where a between 2 and 5; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 109, + "filtered": 5, + "attached_condition": "t1.a between 2 and 5" + } + } +} +explain format=json select * from t1 where a between 12 and 15; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 109, + "filtered": 33.59375, + "attached_condition": "t1.a between 12 and 15" + } + } +} +flush tables; +set @@optimizer_use_condition_selectivity=3; +explain format=json select * from t1 where a between 2 and 5; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 109, + "filtered": 15.78947353, + "attached_condition": "t1.a between 2 and 5" + } + } +} +set @@optimizer_use_condition_selectivity=4; +explain format=json select * from t1 where a between 2 and 5; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 109, + "filtered": 5, + "attached_condition": "t1.a between 2 and 5" + } + } +} +drop table t1; +set @@optimizer_use_condition_selectivity=default; +# +# End of 10.6 tests # diff --git a/mysql-test/main/stat_tables_flush.test b/mysql-test/main/stat_tables_flush.test index abbbb0d6467..4c916f47ad7 100644 --- a/mysql-test/main/stat_tables_flush.test +++ b/mysql-test/main/stat_tables_flush.test @@ -46,5 +46,27 @@ analyze table t1 persistent for all; drop table t1; --echo # ---echo # End of 10.5 tests +--echo # Test that histograms are read after flush +--echo # + +create table t1 (a int); +insert into t1 select seq from seq_1_to_10; + +insert into t1 select A.seq from seq_10_to_20 A, seq_1_to_9 B; +analyze table t1 persistent for all; + +explain format=json select * from t1 where a between 2 and 5; +explain format=json select * from t1 where a between 12 and 15; + +flush tables; +set @@optimizer_use_condition_selectivity=3; +explain format=json select * from t1 where a between 2 and 5; +set @@optimizer_use_condition_selectivity=4; +explain format=json select * from t1 where a between 2 and 5; + +drop table t1; +set @@optimizer_use_condition_selectivity=default; + +--echo # +--echo # End of 10.6 tests --echo # diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index e09370f94c4..9351c1253b0 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -2102,7 +2102,7 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) &column_stats, sizeof(*column_stats) * fields, &index_stats, sizeof(*index_stats) * keys, &idx_avg_frequency, - sizeof(idx_avg_frequency) * key_parts, + sizeof(*idx_avg_frequency) * key_parts, &histogram, hist_size * fields, NullS)) DBUG_RETURN(1); @@ -2145,6 +2145,14 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) key_info->collected_stats->init_avg_frequency(idx_avg_frequency); idx_avg_frequency+= key_info->ext_key_parts; } + /* + idx_avg_frequency can be less than + table_stats->idx_avg_frequency + key_parts + in the case of LONG_UNIQUE_HASH_FIELD as these has a hidden + ext_key_part which is counted in table_share->ext_keyparts but not + in keyinfo->ext_key_parts. + */ + DBUG_ASSERT(idx_avg_frequency <= table_stats->idx_avg_frequency + key_parts); create_min_max_statistical_fields_for_table(thd, table); @@ -2208,7 +2216,7 @@ alloc_engine_independent_statistics(THD *thd, const TABLE_SHARE *table_share, &column_stats, sizeof(Column_statistics) * fields, &index_stats, sizeof(Index_statistics) * keys, &idx_avg_frequency, - sizeof(idx_avg_frequency) * key_parts, + sizeof(*idx_avg_frequency) * key_parts, NullS)) DBUG_RETURN(1); @@ -2232,6 +2240,7 @@ alloc_engine_independent_statistics(THD *thd, const TABLE_SHARE *table_share, index_stats->init_avg_frequency(idx_avg_frequency); idx_avg_frequency+= key_info->ext_key_parts; } + DBUG_ASSERT(idx_avg_frequency <= table_stats->idx_avg_frequency + key_parts); DBUG_RETURN(0); } @@ -2840,11 +2849,12 @@ read_statistics_for_table(THD *thd, TABLE *table, TABLE_SHARE *table_share= table->s; DBUG_ENTER("read_statistics_for_table"); - if (!force_reload && table_share->stats_cb) + if (!force_reload && table_share->stats_cb && + (!want_histograms || !table_share->histograms_exists())) { if (table->stats_cb == table_share->stats_cb) - DBUG_RETURN(table->stats_cb); // Use current - table->update_engine_independent_stats(); // Copy table_share->stats_cb + DBUG_RETURN(table->stats_cb); // Use current + table->update_engine_independent_stats(); // Copy table_share->stats_cb DBUG_RETURN(table->stats_cb); } diff --git a/sql/table.cc b/sql/table.cc index 4badef7d5a1..53d0945dce9 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4596,6 +4596,22 @@ TABLE_SHARE::update_engine_independent_stats(TABLE_STATISTICS_CB *new_stats) } +/* Check if we have statistics for histograms */ + +bool TABLE_SHARE::histograms_exists() +{ + bool res= 0; + if (stats_cb) + { + mysql_mutex_lock(&LOCK_share); + if (stats_cb) + res= stats_cb->histograms_exists(); + mysql_mutex_unlock(&LOCK_share); + } + return res; +} + + /* Free information allocated by openfrm diff --git a/sql/table.h b/sql/table.h index 382692cb7ca..b3144ca75d9 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1161,6 +1161,7 @@ struct TABLE_SHARE MEM_ROOT *mem_root, List *field_list) const; void update_engine_independent_stats(TABLE_STATISTICS_CB *stat); + bool histograms_exists(); }; /* not NULL, but cannot be dereferenced */