vlambda博客
学习文章列表

MYSQL 8 统计信息持久化 与 null

在任何数据库中统计信息是帮助数据库查询中走更适合的查询路径的基础,MYSQL 8 中持久化的统计信息怎么做,怎么能持久化后提高执行计划的稳定性。

默认的情况下,这个参数是打开的

show variables like 'innodb_stats_persistent';

MYSQL 8 统计信息持久化 与 null


实际当中统计信息是存在于mysql.innodb_table_stats   and  mysql.innodb_index_stats 这两个表中的

MYSQL 8 统计信息持久化 与 null

具体每个表变化多少数据量才开始进行统计,要看 innodb_stats_auto_recalc 这个参数,默认打开,并且一个表中的10%的行进行变化了,才开始统计信息的重新计算。

MYSQL 8 统计信息持久化 与 null


实际上下面的某些东西可能和有些开源数据库有类似的地方了,可以调整的参数是在表的层面还是数据库层面,都可以细微的调整了,因为我们不能让每个表的数据的增量都一致,假象一个表一天的增量是100万行,一个是50行,那统计分析如果已按照所有的表一样的方式来进行统计,这显然是有点欠妥。


MYSQL 8 统计信息持久化 与 null

所以上面的截图就是一个类似细微调整的参数

stats_persistent = 1 是要持久化性能计数器

stats_auto_recale 是控制这个表到底要不要进行自动的性能分析,例如有人ORACLE 用的顺手了,很可能会在晚上的时间来跑一边统计分析,这里 stats_auto_recalc 这里的意思是是否你要自动的进行还是手动, 最后的stats_sample_pages 是针对你索引的统计信息的精度,默认是20,增加这个数值可以提高统计信息的精度,当然你也要付出某些磁盘空间,和分析时的cpu等资源。

所以这样就对一个大表是经常被查询的HOT TABLE 还是 COLD TABLE 在这里进行分析,虽然这个表大量插入数据,但实际上查询很少,则可以降低 stats_sample_pages 的随机抽样的数字。相反,则可以适当增加。


MYSQL 8 统计信息持久化 与 null


我们来做一个测试,关于往数据库中插入数据,但之前需要注意的是PYTHON 与MYSQL 8.019相连接需要新的连接方式 mysql_connector_python  而不是之前的方式,上图的还在继续用老的方式需要将你的账户的。

CREATE USER link@'%' IDENTIFIED WITH mysql_native_password BY 'link';  否则连接中会报错


MYSQL 8 统计信息持久化 与 null

另外还有一点是,在统计分析中默认是针对 READ UNCOMMITED  的方式,其中如果有删除的记录,同时被标记的删除记录,还是要记录到统计分析中,所以大量有delete操作的情况下 RC RR 方式获得的统计分析信息就会相对准确率低。

MYSQL 8 统计信息持久化 与 null


所以就可以将 innodb_stats_include_delete 打开。但同样也会将统计分析的时间加大,并且在统计分析时会加重系统的负担。


MYSQL 8 统计信息持久化 与 null

idx_name  n_diff_pfx01 |    1743985 |         100 | name                              idx_name   n_diff_pfx02 |    1761487 |         100 | name,id                        

idx_name   n_leaf_pages |       2722 |        NULL | Number of leaf pages 

idx_name   |  size   |     3175 |      NULL | Number of pages in the index    

从上面的拿出的文字来看,size 是显示整体的page  数量,n_leaf_pages 是展示当前的页节点的page的数量, n_diff_pfx01 是指单列值的不同的情况,n_diff_pfx02 是显示 两列之间不同的值。


按照我们的MYSQL 的主键设置的方式,主键和索引列的值一般是不一样的,所以这里可以认为 n_diff_pfx02 大致就是你目前的表的行数(非准确,因为出发重新统计需要数据变化10%rows)


MYSQL 8 统计信息持久化 与 null

最后需要看一下NULL 值在统计分析中的方式 innodb_stats_method

mysql 提供了3种方式

nulls_equal   所有NULL索引值都被认为是相等的

nulls_unequal  值被认为是不等的,每个NULL形成大小为1的不同的值组。

nulls_ignored  忽略空值


另外这里不便展开,null = null  , no  , null != null , no  , null 在数据库里面到底是一个什么角色,并且要不要被统计到统计信息里面来,都是应该考虑的问题,而MYSQL 将这个问题让用户来选择,实际上着也说明MYSQL 本身也对这个问题没有自己的解决方案,所以...... 


大家在设计表的时候,尽量还是不要NULL 列,即使有,也不要INDEX it.

最后留下一幅图,在正常的语句中,如果有null,都要在查询中添加一个 and  某字段 is null  or  某字段 not is null  ,是有意义的,否则........