Permalink
Browse files

force stats recalculation when "show table status" is called

Summary:
Make innodb_stats_on_metadata a session variable and enforced for both
transient and persistent stats.

Test Plan: added a new test: innodb.innodb_table_status_stats

Reviewers: over

Reviewed By: over
  • Loading branch information...
1 parent 40c51f3 commit 3e82c24f64692926d726d0783ac59c9673fbc214 @rongrong rongrong committed with jtolmer Jan 16, 2015
@@ -0,0 +1,18 @@
+DROP TABLE if exists t1;
+# Create & populate table.
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256)) ENGINE=INNODB;
+# Force a stats update because normal stats calculation is done in background with separate thread
+# thus unpredictable.
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+pass
+1
+# The table currently have 128 records, adding another 10 will not trigger stats recalculation by default (< 10%).
+# Querying the stats should not trigger a stats recalculation by default.
+pass
+1
+# Querying the stats should trigger a stats recalculation when innod_stats_on_metadata is enabled.
+pass
+1
+drop table t1;
@@ -0,0 +1,52 @@
+--source include/have_innodb.inc
+--source include/have_innodb_16k.inc
+
+--disable_warnings
+DROP TABLE if exists t1;
+--enable_warnings
+
+--echo # Create & populate table.
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256)) ENGINE=INNODB;
+
+--disable_query_log
+INSERT INTO t1 VALUES (1, REPEAT('A', 256));
+INSERT INTO t1 (b) SELECT b from t1;
+INSERT INTO t1 (b) SELECT b from t1;
+INSERT INTO t1 (b) SELECT b from t1;
+INSERT INTO t1 (b) SELECT b from t1;
+INSERT INTO t1 (b) SELECT b from t1;
+INSERT INTO t1 (b) SELECT b from t1;
+INSERT INTO t1 (b) SELECT b from t1;
+--enable_query_log
+
+--echo # Force a stats update because normal stats calculation is done in background with separate thread
+--echo # thus unpredictable.
+analyze table t1;
+
+--disable_query_log
+--let $page_count = query_get_value(select count(*) as result from information_schema.innodb_buffer_page where table_name like '%t1%' and access_time > 0, result, 1)
+--let $data_length = query_get_value(select data_length from information_schema.tables where table_name='t1', data_length, 1)
+--eval select $page_count * 16384 = $data_length as pass
+
+--echo # The table currently have 128 records, adding another 10 will not trigger stats recalculation by default (< 10%).
+let $count=10;
+while ($count) {
+ INSERT INTO t1 (b) VALUES (REPEAT('A', 256));
+ dec $count;
+}
+
+--let $page_count = query_get_value(select count(*) as result from information_schema.innodb_buffer_page where table_name like '%t1%' and access_time > 0, result, 1)
+--let $data_length = query_get_value(select data_length from information_schema.tables where table_name='t1', data_length, 1)
+--echo # Querying the stats should not trigger a stats recalculation by default.
+--eval select $page_count * 16384 != $data_length as pass
+
+set session innodb_stats_on_metadata = on;
+--let $page_count = query_get_value(select count(*) as result from information_schema.innodb_buffer_page where table_name like '%t1%' and access_time > 0, result, 1)
+--let $data_length = query_get_value(select data_length from information_schema.tables where table_name='t1', data_length, 1)
+--echo # Querying the stats should trigger a stats recalculation when innod_stats_on_metadata is enabled.
+--eval select $page_count * 16384 = $data_length as pass
+
+--enable_query_log
+
+# Clean up
+drop table t1;
@@ -39,8 +39,6 @@ ERROR HY000: Variable 'innodb_file_format_check' is a read only variable
Expected error 'Read only variable'
SET session innodb_large_prefix='OFF';
ERROR HY000: Variable 'innodb_large_prefix' is a GLOBAL variable and should be set with SET GLOBAL
-SET @@session.innodb_stats_on_metadata='ON';
-ERROR HY000: Variable 'innodb_stats_on_metadata' is a GLOBAL variable and should be set with SET GLOBAL
SELECT IF(@@GLOBAL.innodb_file_format_check, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_file_format_check';
@@ -10,7 +10,8 @@ select @@global.innodb_stats_on_metadata;
@@global.innodb_stats_on_metadata
0
select @@session.innodb_stats_on_metadata;
-ERROR HY000: Variable 'innodb_stats_on_metadata' is a GLOBAL variable
+@@session.innodb_stats_on_metadata
+0
show global variables like 'innodb_stats_on_metadata';
Variable_name Value
innodb_stats_on_metadata OFF
@@ -42,7 +43,7 @@ VARIABLE_NAME VARIABLE_VALUE
INNODB_STATS_ON_METADATA ON
select * from information_schema.session_variables where variable_name='innodb_stats_on_metadata';
VARIABLE_NAME VARIABLE_VALUE
-INNODB_STATS_ON_METADATA ON
+INNODB_STATS_ON_METADATA OFF
set global innodb_stats_on_metadata=0;
select @@global.innodb_stats_on_metadata;
@@global.innodb_stats_on_metadata
@@ -62,11 +63,9 @@ VARIABLE_NAME VARIABLE_VALUE
INNODB_STATS_ON_METADATA ON
select * from information_schema.session_variables where variable_name='innodb_stats_on_metadata';
VARIABLE_NAME VARIABLE_VALUE
-INNODB_STATS_ON_METADATA ON
+INNODB_STATS_ON_METADATA OFF
set session innodb_stats_on_metadata='OFF';
-ERROR HY000: Variable 'innodb_stats_on_metadata' is a GLOBAL variable and should be set with SET GLOBAL
set @@session.innodb_stats_on_metadata='ON';
-ERROR HY000: Variable 'innodb_stats_on_metadata' is a GLOBAL variable and should be set with SET GLOBAL
set global innodb_stats_on_metadata=1.1;
ERROR 42000: Incorrect argument type to variable 'innodb_stats_on_metadata'
set global innodb_stats_on_metadata=1e1;
@@ -46,8 +46,6 @@ SET @@global.innodb_file_format_check='On';
--error ER_GLOBAL_VARIABLE
SET session innodb_large_prefix='OFF';
---error ER_GLOBAL_VARIABLE
-SET @@session.innodb_stats_on_metadata='ON';
#
# Check if the value in GLOBAL Table matches value in variable
@@ -14,7 +14,6 @@ SELECT @start_global_value;
--echo Valid values are 'ON' and 'OFF'
select @@global.innodb_stats_on_metadata in (0, 1);
select @@global.innodb_stats_on_metadata;
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.innodb_stats_on_metadata;
show global variables like 'innodb_stats_on_metadata';
show session variables like 'innodb_stats_on_metadata';
@@ -40,9 +39,7 @@ set @@global.innodb_stats_on_metadata='ON';
select @@global.innodb_stats_on_metadata;
select * from information_schema.global_variables where variable_name='innodb_stats_on_metadata';
select * from information_schema.session_variables where variable_name='innodb_stats_on_metadata';
---error ER_GLOBAL_VARIABLE
set session innodb_stats_on_metadata='OFF';
---error ER_GLOBAL_VARIABLE
set @@session.innodb_stats_on_metadata='ON';
#
@@ -190,7 +190,6 @@ static my_bool innobase_use_checksums = TRUE;
static my_bool innobase_locks_unsafe_for_binlog = FALSE;
static my_bool innobase_rollback_on_timeout = FALSE;
static my_bool innobase_create_status_file = FALSE;
-static my_bool innobase_stats_on_metadata = TRUE;
static my_bool innobase_large_prefix = FALSE;
static my_bool innodb_optimize_fulltext_only = FALSE;
@@ -599,6 +598,13 @@ static MYSQL_THDVAR_STR(tmpdir,
"Directory for temporary files during DDL operations.",
NULL, NULL, "");
+static MYSQL_THDVAR_BOOL(stats_on_metadata,
+ PLUGIN_VAR_OPCMDARG,
+ "Enable statistics gathering for metadata commands such as "
+ "SHOW TABLE STATUS for tables that use transient statistics or persistent "
+ "statistics. (OFF by default)",
+ NULL, NULL, FALSE);
+
static SHOW_VAR innodb_status_variables[]= {
{"adaptive_hash_hits",
(char*) &export_vars.innodb_hash_searches, SHOW_LONG},
@@ -12000,7 +12006,8 @@ ha_innobase::info_low(
DBUG_ASSERT(ib_table->n_ref_count > 0);
if (flag & HA_STATUS_TIME) {
- if (is_analyze || innobase_stats_on_metadata) {
+ bool stats_on_metadata = THDVAR(ha_thd(), stats_on_metadata);
+ if (is_analyze || stats_on_metadata) {
dict_stats_upd_option_t opt;
dberr_t ret;
@@ -12009,13 +12016,7 @@ ha_innobase::info_low(
if (dict_stats_is_persistent_enabled(ib_table)) {
- if (is_analyze) {
- opt = DICT_STATS_RECALC_PERSISTENT;
- } else {
- /* This is e.g. 'SHOW INDEXES', fetch
- the persistent stats from disk. */
- opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY;
- }
+ opt = DICT_STATS_RECALC_PERSISTENT;
} else {
opt = DICT_STATS_RECALC_TRANSIENT;
}
@@ -17529,12 +17530,6 @@ static MYSQL_SYSVAR_BOOL(status_file, innobase_create_status_file,
"Enable SHOW ENGINE INNODB STATUS output in the innodb_status.<pid> file",
NULL, NULL, FALSE);
-static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
- PLUGIN_VAR_OPCMDARG,
- "Enable statistics gathering for metadata commands such as "
- "SHOW TABLE STATUS for tables that use transient statistics (off by default)",
- NULL, NULL, FALSE);
-
static MYSQL_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_transient_sample_pages,
PLUGIN_VAR_RQCMDARG,
"Deprecated, use innodb_stats_transient_sample_pages instead",

0 comments on commit 3e82c24

Please sign in to comment.