GaussDB 统计信息自动收集机制详解,含策略、分区表处理及性能优化建议。
原文标题:GaussDB数据库统计信息自动收集机制
原文作者:牧羊人的方向
冷月清谈:
怜星夜思:
2、文章提到分区表统计信息收集可能存在滞后问题,除了手动收集统计信息外,有没有其他更自动化的解决方案,比如自定义告警或者任务调度?
3、如果确认是由于统计信息不准确导致SQL执行计划劣化,除了收集统计信息和绑定执行计划外,还有没有其他更灵活的优化手段?例如,是否可以临时调整SQL的优化器参数?
原文内容
1、数据库的统计信息自动收集策略
当autovacuum设置为on时,系统会定时启动autovacuum线程(自动清理线程)自动执行VACUUM和ANALYZE命令,回收被标识为删除状态的记录空间,并更新表的统计数据。两次autovacuum的执行间隔时间由参数autovacuum_naptime控制,默认时间为10分钟。
-
对于空表而言,当表中插入数据的行数大于50时,会触发表自动进行ANALYZE。
-
对于表中已有数据的情况,阈值设定为
autovacuum_analyze_threshold+ autovacuum_analyze_scale_factor*reltuples
其中autovacuum_analyze_threshold表示当表上被删除、插入或更新的记录数超过设定的阈值时才会对这个表执行ANALYZE操作,默认值为50;autovacuum_analyze_scale_factor表示触发一个ANALYZE时增加到autovacuum_analyze_threshold的表大小的缩放系数,默认值为10%;reltuples是表的总行数。
这里简单理解就是,如果是一张空表,当增删改超过50行就会在下一个收集间隔内触发统计信息自动收集,如果是非空表,增删改记录数超过50+10%*总行数,即会触发统计信息自动收集。至于上一个收集周期的增删改行数变化,则是在数据库层记录每个表上实际发生的增、删、改行数 (n_tup_ins,n_tup_upd,n_tup_del)。
触发统计信息收集后,会根据系统设定的配置采样,数据库中默认的采样比例是30000行,由GUC参数default_statistics_target控制默认为100*300。这个采样比例也可以设置为百分比,例如1%即按照当前表记录数的1%进行采样,但是对于大表这个采样的数据就过多,可能会带来一些性能损耗。根据最佳实践,这个值设置为默认值即可,毕竟最懂数据库优化器的还是厂商自己。
对于采样的记录数,数据库会对这些行进行统计,计算诸如不同值数量(n_distinct)、空值比例、高频值(MCV)和数据分布直方图(histogram_bounds)等信息。基于样本的统计结果(如平均每页行数、数据分布),结合表的已知总页数(relpages),估算出全表的行数(reltuples)及其他列级特征。其它数据库统计信息收集的方式大体都是这样,也是权衡性能的最佳机制,毕竟统计信息收集也是一种性能消耗,不可能对表尤其是大表进行全部记录的统计。基于抽样的估算统计信息机制大部分时间是准确的,但是针对一些特殊场景可能存在统计信息不准确,尤其是在分区表以及数据倾斜的场景下。
2、分区表的统计信息自动收集策略
分区表(Partitioned Table)指在单节点内对表数据内容按照分区键以及围绕分区键的分区策略对表进行逻辑切分。从数据分区的角度来看是一种水平分区(horizontal partition)策略方式,将表按照指定规则划分为多个数据互不重叠的部分。从数据分布而言,分区表分为主表和子表,主表是一个逻辑上的概念,实际的数据是存放在表分区子表之上,表分区可以增加删除、修改,存放的文件系统也可以不同,主表只需要同步全局的表结构和维护全局分区表的字典信息以及统计信息。
相比较普通表,分区表不仅可以提升数据库查询性能,在分区裁剪的场景下只需要查询指定的分区,不需要对所有分区扫描,从而提升查询效率;另外如果某个分区出现故障,表在其它分区的数据依然可用。那么分区表的统计信息搜集策略是怎样,有两个维度:
-
分区表的维度,当所有分区的增删改达到表统计信息自动收集的阈值,会触发统计信息自动收集,对所有满足条件的分区收集统计信息,并汇总到分区表中;
-
表分区维度,当全局表没有达到自动收集的阈值,但是单个分区的增删改达到这个阈值时,也会触发该分区的统计信息自动收集。从数据库的表现来看,当单个分区的统计信息收集后,并没有同步更新到分区表上。
举个例子,比如某一张分区表有100w数据,10个分区,每个分区平均有10w条数据,当分区2的新插入了2w条数据,对于整张表而言没有达到10%增量变化的阈值,不会触发全局表的统计信息自动收集。但是对于分区2而言,达到了该分区10%增量变化的阈值,会对该分区单独进行统计信息收集。
备注:在GaussDB数据库505.2.1.SPC0800以前版本中表分区的统计信息自动收集只会计算update和delete的记录数,并没有统计insert。不过用最新505.2.1.SPC0900金融稳定版本测试这一块已经包括了insert的记录数,在这一块已经做了优化。
3、如何及时发现和快速应急
-
基础设施层故障:如硬件故障、网络故障和机房环境故障等
-
数据库实例层故障:数据库连接异常、数据库性能下降、事务问题以及内部资源耗尽等
-
数据库服务层故障:数据库服务不可用、数据库认证和授权、数据一致性等
对于数据库性能问题而言,传统的应急几板斧“杀会话、切换、重启、收集统计信息、限流、执行计划绑定”等,真正能快速定位问题并应急的也只有收集统计信息或者执行计划绑定,对于主备切换或者实例重启,并不能根本解决问题,有性能问题依旧;而杀会话或者限流,不可避免带来服务降级,也没解决问题。执行计划劣化的问题最难判定,目前大部分国产数据库并不支持查看历史执行计划信息,也没有类似Oracle数据库执行计划跳变检测的能力,甚至执行计划动态绑定也不支持,仅有类似SQL Patch的绑定功能,复杂的SQL问题场景下并不好使。
参考资料:
