Skip to content

Commit

Permalink
force stats recalculation when "show table status" is called
Browse files Browse the repository at this point in the history
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
Rongrong Zhong authored and jtolmer committed Jan 5, 2016
1 parent 40c51f3 commit 3e82c24
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 27 deletions.
18 changes: 18 additions & 0 deletions mysql-test/suite/innodb/r/innodb_table_status_stats.result
Original file line number Diff line number Diff line change
@@ -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;
52 changes: 52 additions & 0 deletions mysql-test/suite/innodb/t/innodb_table_status_stats.test
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';

#
Expand Down
25 changes: 10 additions & 15 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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",
Expand Down

0 comments on commit 3e82c24

Please sign in to comment.