MySQL innodb统计信息

对innodb 统计信息的控制能够经过以下几个经常使用的variables 来实现mysql

一、innodb_stats_persistent:sql

  这个参数控制着innodb的统计信息是否持久化到磁盘,先说明一下持久化到磁盘是什么意思;一般来讲统计信息只保存在内存中,也就是说若是mysql服务一重启那么以前数据库

  全部的统计信息都没有了,这个状况下mysql就要从新收集&计算了;若是统计信息持久化到磁盘了,那么就能够直接从磁盘中读取;异步

  为了真正的能够达到红统计信息持久化到磁盘光是innodb_stats_persistent=on是作不到的;innodb_stats_persistent=on 只是说明了打开了mysql把表的统计post

  信息持久化到磁盘的能力,可是这个能力用不用不是由表本身说了算;在create table 语句中指定STATS_PERSISTENT=1这个时候表就支持持久化工能了。性能

  create table t(x int,y int) STATS_PERSISTENT=1;

 

二、由1中的描述可知 innodb的表能够分红两大类、一类是支持持久化的表,一类是不支持持久化的表;它们各自的统计信息的收集方式又能够经过不一样的变量来控制学习

 

三、innodb_stats_persistent_sample_pages 持久化统计信息的采样页测试

 

四、innodb_stats_transient_sample_pages 非持久化统计信息的采样页优化

 

五、innodb_stats_auto_recalc 变动超过10%的时候要不要自动收集统计信息spa

 

六、innodb_stats_on_metadata 执行show table status | information_schema.tables 时是否自动收集统计信息

 

7. 咱们将一条查询SQL提交给MySQL以后,MySQL在进行真正的查询操做以前一般会经历两个阶段:SQL解析和查询优化。在SQL解析过程当中,MySQL会将SQL解析为一个树状结构,而在查询优化阶段,MySQL会决定以什么方式进行查询,那么MySQL以什么方式进行查询的抉择依据是什么呢?答案就是这篇文章要介绍的MySQL统计信息,由于我厂的MySQL实际使用的是Percona分支,所以本文相关的实验知识是基于Percona分支的。

带着问题

  • MySQL统计的信息包括什么内容?是用来作什么的?
  • MySQL统计信息基于表和索引,表和索引是要变化的,那么MySQL是如何保证数据的时效性的?
  • MySQL的统计机制有什么问题?统计策略如何选择?


MySQL统计信息

持久化存储->
对于InnoDB存储引发来讲,统计信息分别存储在mysql库的下面两张表中:

  • innodb_table_stats
  • innodb_index_stats

innodb_table_stats存储表维度的统计信息,innodb_index_stats存储索引维度的统计信息。在持久化存储的状况下,当设置为自动更新统计信息的时候且表中有超过10%的数据被更新的时候会执行统计信息的从新计算,并且从新统计不是当即执行的,而是等了一段时间,这个值在MySQL中被定义为MIN_RECAL_INTERVAL=10(秒)。

易失性存储->

当innodb_stats_persistent=OFF的时候,MySQL统计信息存储在内存以后,很显然当重启数据库的时候,这些信息会丢失。

在易失性存储的状况下,统计信息从新计算的时机和持久化存储方式是不一样的,咱们来看看哪些条件会触发该状况下统计信息的从新计算:

  • 执行ANALYZE TABLE命令
  • 执行以下命令:SHOW TABLE STATUS, SHOW INDEX。
  • 在innodb_stats_on_metadata选项开启的状况下查询INFORMATION_SCHEMA.TABLES表或INFORMATION_SCHEMA.STATISTICS表
  • 经过--auto-rehash参数开启客户端链接,--auto-rehash参数致使InnoDB表被打开,InnoDB表被打开致使统计信息被从新计算
  • 表被第一次打开
  • 距离上次统计以后,表的1/16的数据被更新


了解在什么方式下统计信息会被从新计算对于数据库的使用优化是有帮助的,好比咱们能够破坏一些条件而让事情向着对咱们有力的一面发展。

统计内容:
MySQL统计信息包括哪些内容呢?MySQL分别从表维度和索引维度构建统计信息。

表统计信息:
innodb_table_stats表存储的是表维度的统计信息,innodb_table_stats表有6个字段,他们的各字段相关定义以及含义以下表所示:

字段名 字段类型 字段含义
database_name    verchar(64)    统计信息所属表的数据库名
table_name    verchar(64)    统计信息所属的表名
last_update    timestamp    统计信息最后一次更新的时间
n_rows    bigint(20) unsigned    表所包含的行数
clustered_index_size    bigint(20) unsigned    汇集索引的页的数量
sum_of_other_index_size    bigint(20) unsigned    其余索引所占的页的数量


我找了一张咱们现存的表测试一下:

如上图所示,CL_CommunityNavStatInfo表当前的记录数为5281。

上面咱们看到表中实际有5281行数据,可是统计出来的是5228行数据,这是由于什么呢?这个问题留在精度问题部分进行讨论。

索引统计信息
innidb_index_stats表存储的是索引维度的统计信息,innodb_index_stats表有8个字段,他们的各字段相关定义以及含义以下表所示:

字段名  字段类型  字段含义
database_name    varchar(64)    统计信息所属表的数据库名
table_name    varchar(64)    统计信息所属表名
index_name    varchar(64)    统计信息所属索引名
last_update    timestamp    统计信息更新的时间
stat_name    varchar(64)    统计信息名称
stat_value    bigint(20) unsigned    统计值
sample_size    bigint(20) unsigned    采样大小
stat_description    varchar(64)    统计描述信息

 

咱们依然使用上面测试用到的CL_CommunityNavStatInfo表进行测试,先看看CL_CommunityNavStatInfo表的索引定义:


CL_CommunityNavStatInfo表创建了三个索引,咱们经过innodb_index_stats表来看看这三个索引的统计信息:


上图为表CL_CommunityNavStatInfo全部索引的统计信息,好比最后一行,size表明主键汇集因此所占页数大小为161,叶子节点所占空大小为128页,id的区分度为5228,这个数字其实也是统计的表的行数,sample_size为20表示采样页数。

精度问题
采样大小

上面提到了sample_size这个数字,其实MySQL的统计数据是基于采样数据估算的,而采样的大小是用户可控的,默认值为20,咱们能够经过修改采样大小来控制统计信息的精确性,同时这也会影响性能。好比咱们用下面命令将采样大小调整为200:

SET global innodb_stats_persistent_sample_pages=200;
200是咱们随表挑的一个大于全部数据页数的数字,这样保证统计信息基于全量数据统计,经过ANALYZE TABLE CL_CommunityNavStatInfo;命令从新统计以后,再来看看统计信息:



是否是无比的准确?再继续看看索引的统计信息:


如今的统计信息已是基于全量的数据统计了,虽然数据准确了,可是咱们同时也损失了一部分的性能。

统计时机

定时轮训

统计时机关心的是何时进行统计信息的更新。innodb_stats_auto_recalc参数用于控制是否让MySQL自行在须要的时候更新统计信息,当它的值为ON的时候,统计信息的从新计算是异步的,MySQL有一个线程专门用来作这个事情,这个线程每隔10秒钟回去看看要不要进行统计,不然咱们须要使用ANALYZE TABLE命令来保证统计信息的时效性。那么咱们是选择将统计信息的更新权利彻底霸占仍是将其受权给MySQL让它自行更新呢?这个问题留给读者思考。总结本文分别从MySQL统计信息的存储、内容、精度和统计时机方面对MySQL统计信息进行了必定的学习,了解了MySQL统计信息的相关知识,我认为咱们至少能够解决一些实际问题了。好比:咱们当前应用的数据源MySQL关于统计方面的配置有没有问题?咱们是否能够试着经过调整采样大小来控制统计信息的精确度?从而影响SQL优化器的决策?咱们是否能够经过统计信息来估算表中数据所占用的存储空间?……等等。

相关文章
相关标签/搜索