首页 > 学院 > 开发设计 > 正文

MySQL统计信息收集及磁盘util指标问题

2019-11-08 20:32:56
字体:
来源:转载
供稿:网友

背景QQ群里,一位朋友问了如下的问题: 这里写图片描述

问题是:只查询一个information_schema.tables;表,为啥会有几百个Opening tables?

原因:此操作会触发表统计信息的收集。关于information_schema中表的查询都要去真正的表查看,所以慢。

MySQL如何收集统计信息? Analyze table收集表和索引统计信息,适用于MyISAM和InnoDB; 对于innodb表,还可以使用以下选项: 1 表第一次打开的时候

2 表修改的行超过1/16或者20亿条 ./row/row0mysql.c:row_update_statistics_if_needed

3 执行show index/table或者查询information_schema.tables/statistics表时 在访问以下表时,innodb表的统计信息可自动收集 information_schema.TABLES information_schema.STATISTICS information_schema.PARTITIONS information_schema.KEY_COLUMN_USAGE information_schema.TABLE_CONSTRAINTS information_schema.REFERENTIAL_CONSTRAINTS information_schema.table_constraints

innodb_stats_on_metadata参数用来控制此行为,设置为false时不更新统计信息 Innodb_stats_sample_pages每次收集统计信息时采样的页数,默认为8 每个表维护一个stat_modified_counter,每次DML更新1行就加1,直到满足阈值则自动收集统计信息,并把此值清0; 函数dict_update_statistics用于更新统计信息,但若有多个线程同时检测到阈值,会导致多次调用,浪费了系统资源; 可以直接修改代码,让dict_update_statistics对stat_modified_counter加锁,避免并发执行;http://dinglin.iteye.com/blog/1815392

5.6提供选项innodb_stats_persistent,默认on,将analyze table产生的统计信息保存于磁盘,直至下次analyze table为止,此举避免了统计信息动态更新,保证了执行计划的稳定,对于大表也节省了收集统计信息的所需资源; 除非当前sql执行计划不佳,否则不应经常analyze table收集统计信息。

Innodb_stats_method和myisam_stats_method 计算统计信息时,拥有相同key PRefix的行算作一个value group(类似Oracle索引中的num_distinct,其值越多意味着索引选择性越好),average group size是非常重要的指标,即平均一个索引值返回的表行数,主要有两个用途: 1估算每次ref access要读取多少行 2 估算一个partial join要产生多少行 (…) join tab on tab.key = expr 由此可知,average group size越高则索引选择性越低,表基数即value group数量计算公式为N/S(N:表行数 S:average group size),可通过show index查看

除了主键,索引不可避免的会遇到Null(对于<=>操作符,NULL和Non-null被同等对待,而Null = Null则会返回false),mysql将NULL视作无穷小; 收集统计信息时,为了灵活的处理Null,InnoDB/MyISAM各引入一个参数Innodb_stats_method/myisam_stats_method,分别三个候选值:nulls_equal/nulls_unequal/nulls_ignored(其中innod_stats_method只有全局变量) Nulls_equal:所有Null都相等,即算作一个value group;若Null过多则会导致average group size偏大 Nulls_unequal:所有Null互不相同,每个算作一个value group;如果non-null group size过大且null数量过多,此设置会拉低整体的average group size,可能导致滥用索引 Nulls_ignored:忽略Null 对于已经收集的统计信息,无法分辨其采用了那种方式;对于非InnoDB/MyISAM表,只有一种收集方式,即nulls_equal; 手工收集统计信息需要调用analyze table,但若表自上次analye至今没有任何改动,即便调用此命令实际也不会收集统计信息,需先让统计信息过期(插入一行再删除即可) Mysql也可自动收集,诸如bulk insert/delete以及某些alter table语句均会触发。

如何查看统计信息 Show index from table或查看information_schema.statistics表 Show table status或information_schema.tables表

http://www.mysqlperformanceblog.com/2011/10/06/when-does-innodb-update-table-statistics-and-when-it-can-bite/ http://www.mysqlperformanceblog.com/2008/09/03/analyze-myisam-vs-innodb/

iostat中的util、srvctm、await %util与硬盘设备饱和度

%util表示该设备有I/O(即非空闲)的时间比率,不考虑I/O有多少,只考虑有没有。由于现代硬盘设备都有并行处理多个I/O请求的能力,所以%util即使达到100%也不意味着设备饱和了。举个简化的例子:某硬盘处理单个I/O需要0.1秒,有能力同时处理10个I/O请求,那么当10个I/O请求依次顺序提交的时候,需要1秒才能全部完成,在1秒的采样周期里%util达到100%;而如果10个I/O请求一次性提交的话,0.1秒就全部完成,在1秒的采样周期里%util只有10%。可见,即使%util高达100%,硬盘也仍然有可能还有余力处理更多的I/O请求,即没有达到饱和状态。那么iostat(1)有没有哪个指标可以衡量硬盘设备的饱和程度呢?很遗憾,没有。

await是单个I/O所消耗的时间,包括硬盘设备处理I/O的时间和I/O请求在kernel队列中等待的时间,正常情况下队列等待时间可以忽略不计,姑且把await当作衡量硬盘速度的指标吧,那么多大算是正常呢? 对于SSD,从0.0x毫秒到1.x毫秒不等,具体看产品手册; 对于机械硬盘,可以参考以下文档中的计算方法: http://cseweb.ucsd.edu/classes/wi01/cse102/sol2.pdf 大致来说一万转的机械硬盘是8.38毫秒,包括寻道时间、旋转延迟、传输时间。

svctm:已被废弃的指标,没什么意义,svctm=[util/tput]


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表