1.统计信息不准确的影响

统计信息不准确一般会导致MySQL优化器无法选择正确的索引,从而导致优化器选择错误的索引或者不走索引,引起索引失效,导致大量慢查询

2.什么情况下会导致统计信息不准确?

一般来说,大体分为以下两种情况:

  1. 统计信息未及时更新,不正确的统计信息导致索引失效。
  2. 表中碎片过多,导致Cardinality不准确,计算错误。

下面就两种场景进行细谈:

统计信息未及时更新

在这个话题之前先看一些参数:

FOR MySQL 5.7: 一般来说统计信息由下面的参数控制:

innodb_stats_persistent:控制统计信息是否持久化,默认打开。

innodb_stats_auto_recalc: 控制表多少比例的行被修改后自动更新统计信息,默认是10%,默认打开。

innodb_stats_persistent_sample_pages: 开启统计信息持久化之后索引统计时采样的页面数,默认20个页面,太大会导致采样时间过久影响性能。

innodb_stats_method: 统计信息在遇到NULL值如何进行处理,默认NULL值相等即nulls_equal。

另外还有两张表可以看到统计信息的详细:

mysql.innodb_index_statsmysql.innodb_table_stats 这两张表会存储一些详细信息,表结构如下:

mysql 大数字 精度 mysql精度丢失_mysql

mysql 大数字 精度 mysql精度丢失_big data_02


从两个表的信息中可以看到统计信息的最后时间。

所以从参数含义上可以看到会存在统计信息更新不及时导致统计信息出现问题。

For MySQL 8.0:

出了上面的参数外,引入一个新参数:

information_schema_stats_expiry:统计信息在缓存中的时间,默认是86400s 1天。

表碎片过多

先看一个图片:

mysql 大数字 精度 mysql精度丢失_sql_03


Cardinality:表里面统计的多少个不一样的值,值越大说明索引的区分度越高。

在MySQL当中,索引即数据,但是如果表中碎片过多,那么Cardinality值的统计就会受到影响,

比如碎片占表数据一半大小,那么统计的时候这些被标记的位置都为NULL即都是相同的值,导致

Cardinality值变小,影响优化器选择正确的索引。

3.如何解决统计信息不准确?

一般来说我们有三种操作都可以实现:

  1. Analyse table
  2. optimize table
  3. alter table T engine=innodb

以上三种方式都可以重新生成统计信息。区别是

第一种是只针对统计信息去做的。

第二三种不仅会会重新整理统计信息,而且会重建表,回收表中的碎片。

mysql 大数字 精度 mysql精度丢失_big data_04

参考网址: https://www.modb.pro/db/77939