写点什么

统计信息十问: 你不了解的那些事儿

  • 2022 年 7 月 11 日
  • 本文字数:2848 字

    阅读完需:约 9 分钟

作者: h5n1 原文来源:https://tidb.net/blog/92447a59


  统计信息是经常遇到的问题,官方文档和 TUG 上已有较多关于统计信息的文章,本文对遇到的统计信息问题在分析、测试的基础上进行总结。


1、 stats_meta 如何更新?


       Stats_meta 主要记录表、分区的记录 DML 数量,当 stats-lease 大于 0 时 (默认为 3 秒,当为 0 时则关闭该更新功能), 每隔 20*statsLease 会更新 stats_meta 信息 (TiSpark 需要开启 enableUpdateTableStatistics), 对于执行过统计信息收集的表 auto-analyze 依据 modify_count/row_count 和 tidb_auto_analyze_ratio 决定是否执行。对于不同的操作 modify_count/row_count 2 个列数值处理方式不同:


  •   Insert: 增加 modify_count,增加 row_count。

  •   Delete: 增加 modify_count,减少 row_count。

  •    Update: 增加 modify_count,row_count 不变。


2、  Auto-analyze 是谁执行的?


       同 DDL 一样,auto-analyze 会选出一个 tidb server 作为 stats owner 节点,由 stats owner 节点执行,成为 owner 后 tidb.log 会有如下信息, 并且 auto-analyze 的相关日志会写入 owner  的 tidb.log,stats owner 一般和 ddl owner 为同一 tidb,可通过 TIDB_IS_DDL_OWNER() 查询当前连接到的 tidb server 是否为 owner, 或使用 curl http://tidb_ip:10080/info/all 查看哪个 tidb 为 Owner。



3、  Auto-anlyze 什么时候执行?


       Tidb 启动时会启动一个 goroutine 每隔 statlease(3 秒) 时间执行 auto-analyze 检查是否有满足条件的表需要收集统计信息:


  (1)    前提条件:stats-lease参数>0,开启auto-analyze(performance.run-auto-analyze参数)且在tidb\_auto\_analyze\_start\_time/end\_time变量指定的时间内。
(2) 未analyze过的表:表中数据row\_count≥1000条,且在20\*statsLease 时间内没有DML执行。
(3) 已做过analyze的表:表中数据row\_count≥1000条,当即当某个表的修改行数与总行数的比值(modify\_count/row\_count)> tidb\_auto\_analyze\_ratio后。
(4) 新建索引后,对于5.3.0、5.2.2之前版本,新建索引后无论是否位于规定的analyze-time时间内都会触发auto-analyze。
复制代码



4、  auto-analyze 和 manual analyze 有什么区别?


       在执行统计信息收集时 auto-analyze 和 manual analyze 都执行 analyze SQL,不同的是 auot-analyze 是内部 session 执行,对于内部 session tidb 有资源限制,能提升统计信息收集效率的参数值都设置为 1, 因此会导致 auto-anlyze 比 manual analyze 执行慢。






5、  Auto-analzye 失败原因?


       比较常见的 auto-analyze 失败原因是执行时间过长超过了 GC safepoint,在计算 safepoint 时,会从 pd 获取当前时间 now 并减去 24 小时 (max-txn-time-use) 作为 startTSLowerLimit,,然后获取所有活动事务的 processlist 的 startts, 以 min(startTSLowerLimit,starts) 为 safepoint 时间。 触发 auto analyze 的内部 session 并不会被统计在 processlist 中 (show processlist 也不会展示),这样就出现 safepoint > auto analyze 事务的 start_ts 的情况,导致 auto analyze 失败。6.0 版本后会进行改进。



6、  为什么无法看到更多 Analyze 历史记录?


  Analyze table的历史记录可通过show  analyze status命令查看,目前存在以下问题:
(1) 只能查看近20条记录,且记录信息在内存中,tidb server重启后信息丢失。
(2) 只能看到本tidb server 内执行的分析记录,无法看到全局信息。
根据<https://github.com/pingcap/tidb/pull/32215>描述后续版本中会将分析记录到 mysql.analyze\_jobs,show analyze status可以查看近30条记录
复制代码


7、  直方图里为什么看不到列信息?


   show stats\_buckets/stats\_histograms 只会显示加载到内存中的统计信息。系统启动时会将表、索引级统计信息加载到stats cache内,因此表和索引级的统计信息是常驻内存的,每隔 stats-lease 时间,TiDB 会检查统计信息是否有更新,有的话被加载到内。
对于列的统计信息,其数据量较大占用的的内存较多,当有查询条件涉及到该列时,tidb 才会将该列的统计信息加载到内存中,每隔 stats-lease 时间,会检查是否有列统计信息需要备加载到内存。
5.4版本中推出统计信息同步加载实验功能,在执行SQL时同步将直方图、TopN、CMSketch 等信息加载,通过参数tidb\_stats\_load\_sync\_wait控制。
复制代码




8、 tidb_analyze_version=2 时 oom 候如何处理?


       tidb_analyze_version 是 5.1.0 版本引入的实验特性,在 5.1、5.2 版本被设置成了默认值 (一个小小失误),所以经常在这 2 个版本看到系统甚至在没有什么查询的情况下 tidb server 内存增长或 oom,是由于在 version=2 时收集统计信息后 channle 未关闭的 bug 造成 (5.3 版本修复)。可按如下步骤处理:


  (1)    设置全局变量 tidb\_analyze\_version 为 1
复制代码


        set @@global.tidb_analyze_version = 1;


 (2)    使用如下的 SQL 生成 DROP STATS 的语句并执行。
Tidb在收集统计信息是如果表内已经有统计信息则按表内记录的统计信息version来收集,因此需要删除现有统计信息才能使version=1生效。
复制代码


          select distinct(concat(‘DROP STATS ‘,table_schema, ‘.’, table_name,’;’)) from   information_schema.tables, mysql.stats_histograms where stats_ver = 2 and table_id = tidb_table_id ;


 (3)    手动或等待 auto-analyze 重新收集
复制代码


9、 Feedback 有什么作用?


       Feedback 是 2.1 版本中引入的功能,根据 SQL 实际执行时统计的行数等信息和生成执行计划的预估信息做比对,根据对比的差异去更新统计新 (stats-lease=0 则不更新统计信息),主要包括直方图和 CM-Sketch, 其主要目的是在未能及时收集统计信息的情况下,能够在 SQL 执行后使用最准确的数据来更新统计信息。


  在 v5.0 版本之前,TiDB 会以 feedback-probability 的概率收集反馈信息,由于该功能尚不完善,有可能造成panic/oom,因此5.0版本前建议手动关闭。 对于 v5.0 版本该功能默认关闭,不建议开启此功能。
复制代码


10、 analyze SQL 中选项的默认值是多少?


       Analyze 语句可以使用选项控制每类统计信息采样时使用的值:


       WITH num BUCKETS 用于指定生成直方图的桶数量上限,默认 256,上限 1024。


       WITH num TOPN 用于指定生成 TOPN 数目的上限,默认 20,上限 1024。


       WITH num CMSKETCH DEPTH 用于指定 CM Sketch 的深度,默认 5。


       WITH num CMSKETCH WIDTH 用于指定 CM Sketch 的宽度,默认 2048。


       WITH num SAMPLES 用于指定采样的数目,默认 10000,上限 500000  (即使指定了仍需扫描所有行 https://asktug.com/t/topic/243035/13)


       WITH FLOAT_NUM SAMPLERATE 用于指定采样率,范围 (0,1] (5.3 版本后)。


发布于: 刚刚阅读数: 2
用户头像

TiDB 社区官网:https://tidb.net/ 2021.12.15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
统计信息十问: 你不了解的那些事儿_实践案例_TiDB 社区干货传送门_InfoQ写作社区