本篇先容 MySQL 表如何盘算统计信息。表统计信息是数据库基于成本的优化器最重要的参考信息;统计信息禁绝确,优化器可能给出不够优化的执行计划或者是错误的执行计划。对统计信息的盘算分为非持久化统计信息(实时盘算)与持久化统计信息。非持久化统计信息统计信息没有生存在磁盘上,而是频繁的实时盘算统计信息;每次对表的会见都市重新盘算其统计信息;假设针对一张大表的频繁查询,那么每次都要重新盘算统计信息,很泯灭资源。
持久化统计信息把一张表在某一时刻的统计信息值生存在磁盘上;制止每次查询时重新盘算;如果表更新不是很频繁,或者没有到达 MySQL 必须重新盘算统计信息的临界值,可直接从磁盘上获取;纵然 MySQL 服务重启,也可以快速的获取统计信息值;统计信息的持久化可以针对全局设置也可以针对单表设置。接下来,详细说 MySQL 统计信息如何盘算,何时盘算,效果评估等问题。在 MySQL Server 层来控制是否自动盘算统计信息的漫衍,而且来决议是持久化还是非持久化。
一、持久化统计相关参数:innodb_stats_persistent :是否开启统计信息持久化,默认开启。innodb_stats_auto_recalc :是否自动重新盘算持久化统计信息,默认开启。
二、详细的更新计谋为:当一张表数据变化凌驾 10% 后,MySQL 会针对这张表统计信息的更新时间戳做一个判断,检查最后一次更新的时间是否凌驾 10 秒;如果不到 10 秒,把这张表加到一个统计信息更新行列中,到时间了再重新盘算;如果凌驾了 10 秒,直接重新盘算,而且更新时间戳。现在这个超时时间写死在 MySQL 代码里,暂时不能更改。不外在某些 MySQL 分支版还可以控制这个时间,好比 Percona。
innodb_stats_include_delete_marked :更新持久化统计信息时,是否会盘算已经标志为删除的行。默认是关闭的,会获取未提交的脏数据。
开启这个选项,MySQL 盘算统计信息时只会思量已经提交的数据。innodb_stats_persistent_sample_pages :用于更新持久化索引漫衍或者其他统计信息的随机基数页,默认 20 个。页数越多,统计信息也就越准确,也就有助于查询优化器选择最优的查询计划。什么时候思量更改这个值呢?当查询计划不是很准确时。
好比对比指定表在系统表 mysql.innodb_index_stats 的数据跟 distinct 查询的效果,如果相差太大,可以思量增加这个值。当 analyze table 变的很是慢时,可能是这个值设置的太大了,此时要思量减小这个值。
三、非持久化统计信息参数innodb_stats_transient_sample_pages:设置非持久化统计信息的采样页数目,默认 8 个。innodb_stats_on_metadata:当统计信息设置为非持久化时生效,默认关闭。参数 innodb_stats_persistent 为 0 或者建表时属性 STATS_PERSISTENT=0 才起作用。当开启后,对以下元数据的会见会自动更新统计信息:show table statusshow indexinformation_schema.tablesinformation_schema.statistics所以开启这个选项会分外增加会见表的开销,特别是大表。
另有一些其他的场景会自动更新非持久化统计信息,好比:表第一次被会见;InnoDB 检测到有十六分之一的表自从上次统计信息盘算后被更新了,这时触发自动更新;MySQL 客户端默认选项 --auto-rehash 打开所有 InnoDB 表,导致所有 InnoDB 表被自动更新统计信息;四、表属性控制STATS_AUTO_RECALC用来指定是否要自动盘算指定 InnoDB 表的统计信息。三个值:default, 0, 1default:也就是默认值,依赖 server 端参数 innodb_stats_auto_recalc 的设置效果0:表现禁用统计信息的自动重新盘算,也就是永远不重新盘算,需要手动执行 analyze table1:表现当表数据有 10% 的数据变化后,则重新盘算持久化统计信息。STATS_PERSISTENT用来指定是否要开启指定 InnoDB 表的统计信息持久化。三个值:default, 0, 1default:依赖 server 端参数 innodb_stats_persistent 的设置0:表现不需要持久化统计信息1:表现开启持久化统计信息STATS_SAMPLE_PAGES用来指定盘算统计信息时的采样页数量。
五、手动更新统计信息analyze table 用来手动更新表统计信息。建议在业务低峰时执行。
六、持久化表统计元数据信息优化器通过两张元数据内外的数据来决议查询最优执行计划。表统计信息生存在表 mysql.innodb_table_stats 里好比表 ytt_sample_persist 的统计信息重要列说明:n_rows:表的行数clustered_index_size:主键的数据页个数sum_of_other_index_sizes:二级索引的数据页个数以下例子可以看到表 ytt_sample_persist 表行数或许为 36W 行,聚簇索引页数为 15162,二级索引页数为 4113。
这些值都是基于采样页来盘算的,所以是一个预估值。mysql> select n_rows,clustered_index_size,sum_of_other_index_sizes from innodb_table_stats where database_name ='ytt' and table_name = 'ytt_sample_persist';+--------+----------------------+--------------------------+| n_rows | clustered_index_size | sum_of_other_index_sizes |+--------+----------------------+--------------------------+| 356960 | 15162 | 4113 |+--------+----------------------+--------------------------+1 row in set (0.00 sec)其实表 ytt_sample_persist 真实数据为 40W 行。mysql> select count(*) from ytt_sample_persist;+----------+| count(*) |+----------+| 406644 |+----------+1 row in set (0.90 sec)强制更新统计信息,mysql> analyze table ytt_sample_persist;+------------------------+---------+----------+----------+| Table | Op | Msg_type | Msg_text |+------------------------+---------+----------+----------+|+------------------------+---------+----------+----------+1 row in set (0.28 sec)统计信息已经更新为最新,数据又离真实数据靠近一点。mysql> select n_rows,clustered_index_size,sum_of_other_index_sizes from innodb_table_stats where database_name ='ytt' and table_name ='ytt_sample_persist';+--------+----------------------+--------------------------+| n_rows | clustered_index_size | sum_of_other_index_sizes |+--------+----------------------+--------------------------+| 387202 | 16380 | 4562 |+--------+----------------------+--------------------------+1 row in set (0.01 sec)索引统计信息生存在表 mysql.innodb_index_stats 里好比表 ytt_sample_persist 索引统计信息Index_name:索引名字stat_name / stat_value:统计名字和对应的值sample_size:采样页个数stat_description:统计名字详细信息形貌好比表 ytt_sample_persist 的团结主键统计信息如下:stat_name 显示的值 n_diff_pfx01 代表团结主键中第一个列状态名字,对应的 stat_value 为第一个列的唯一值个数;n_diff_pfx02 代表第二列状态名字,对应的 stat_value 为前两列的唯一值个数,以此类推。
n_leaf_pages /stat_value 代表叶子节点的页数目;size 代表索引的总页数。mysql> select index_name,stat_name,stat_value,sample_size,stat_description from innodb_index_stats where database_name ='ytt' and table_name ='ytt_sample_persist' and index_name = 'PRIMARY';+------------+--------------+------------+-------------+-----------------------------------+| index_name | stat_name | stat_value | sample_size | stat_description |+------------+--------------+------------+-------------+-----------------------------------+| PRIMARY | n_diff_pfx01 | 14137 | 20 | i1 || PRIMARY | n_diff_pfx02 | 75398 | 20 | i1,i2 || PRIMARY | n_diff_pfx03 | 387202 | 20 | i1,i2,i3 || PRIMARY | n_leaf_pages | 15708 | NULL | Number of leaf pages in the index || PRIMARY | size | 16380 | NULL | Number of pages in the index |+------------+--------------+------------+-------------+-----------------------------------+5 rows in set (0.00 sec)那关于表的统计信息相关知识点就先容到此,相识这块对我们优化 SQL 来说,会越发驾轻就熟。
总结简朴总结下,本篇主要先容了 MySQL 表和索引的统计信息盘算,包罗持久化统计信息与非持久化统计信息。如果后期有 SQL 走的执行计划差池,或者不是最优的,那就可以断定相关统计信息太旧了,需要实时更新。
好比有时候多表 JOIN 的顺序差池,导致查询效率变差,需要人工介入等等。关于 MySQL 的技术内容,你们另有什么想知道的吗?赶快留言告诉小编吧!。
本文来源:AOA官方入口-www.ywgbfs.com