# [Critical bug] 关于TiDB后端定期读取mysql.stats_fm_sketch表导致应用程序查询延迟抖动的说明

## Issue

ONCALL-2892 内部生产集群 - v5.0.0 - 查询的返回时间抖动幅度过大

<https://asktug.com/t/topic/69611> tidb 系统查询较多

应用查询量不大但耗时波动大（几十毫秒到几秒之间）：在 ONCALL-2892 中查询几千条数据，耗时在 0.01s~2.75s 之间波动。

监控发现网卡监控发现带宽几乎被打满：

Dashboard 慢查询中出现 SELECT value FROM mysql.stats_fm_sketch WHERE table_id = ? AND is_index = ? AND hist_id = ?：

mysql.stats_fm_sketch 数据量：执行 SELECT count(*) FROM mysql.stats_fm_sketch 发现数据量非常大，如在 ONCALL-2892 中，stats_fm_sketch 数据量超过了十万。

相关 Issues : ONCALL-2892 内部生产集群 - v5.0.0 - 查询的返回时间抖动幅度过大 <https://asktug.com/t/topic/69611> tidb 系统查询较多

## Root Cause

在开发TiDB 5.0时，我们优化了分区修剪并完善了分区表的一些统计数据。在这个过程中，我们引入了新的分区修剪模式 "动态"，并使TiDB在分析后将每个分区的统计结构fm-sketch存储到内部表mysql.stats_fm_sketh。

由于一个bug，陈旧的fm-sketches不能被统计的GC处理清除，所以最后在mysql.stats_fm_sketch中留下大量不必要的记录。

而为了获取最新的统计数据，TiDB会定期读取mysql.stats_fm_sketch，所以如果该表包含大量不必要的记录，这种读取会耗费过多的资源，从而影响用户的查询并导致抖动。

## Diagnostic Steps

N/A 

## Resolution

1. 确保 @@tidb_partition_prune_mode 的值为 “static”

2. 设置脚本，执行 delete 语句定期清空 mysql.stats_fm_sketch 中的数据：delete * from mysql.stats_fm_sketch

修复版本 已在 v5.0.2（tidb/pull/24357 ）和 master（tidb/pull/23830）上修复，修复方法是：

   1. 存储某个表新的 fm-sketch 结构时，会把原有的 fm-sketch 删除，相当于替换掉了原有的数据；

   2. 修复统计信息 GC 过程，使得不需要的 fm-sketch 数据（如表已经被 drop）能被正确删除；

   3. 只会在 dynamic 模式打开时，对分区表进行 fm-sketch 存储；