mysql.stats_top_n 记录太多了 ,请尽快优化

为提高效率,请提供以下信息,问题描述清晰能够更快得到解决:
【 TiDB 使用环境】
v5.2.3

【概述】 场景 + 问题概述
dashboard 流量可视化 发现读取热点基本都是 mysql.stats_top_n


SELECT COUNT(1) FROM mysql.stats_top_n
这个表也太疯狂了吧 7615288 这么多条记录 # 5.0当时也是有大量的垃圾统计信息

这个表还有BLOB大字段
每个table_id 有大量的记录条数 是不是GC清理不及时

【背景】 做过哪些操作

【现象】 业务和数据库现象

【问题】 当前遇到的问题,参考 AskTUG 的 Troubleshooting 读性能慢-慢语句

【统计信息是否最新】

    【执行计划内容】

    【 SQL 文本、schema 以及 数据分布】

【业务影响】

【TiDB 版本】
5.2.3
【附件】 相关日志及监控(https://metricstool.pingcap.com/)

  • TiUP Cluster Display 信息
  • TiUP CLuster Edit config 信息
  • TiDB-Overview Grafana监控
  • TiDB Grafana 监控
  • TiKV Grafana 监控
  • PD Grafana 监控
  • 对应模块日志(包含问题前后 1 小时日志)
1 个赞
  1. 此表为 相关 Table 的统计信息对外查询的一个内部系统表。
  2. 有关 top n 的统计信息知识详见。https://docs.pingcap.com/zh/tidb/stable/statistics/#top-n-信息
    3.首先说明下面的操作存在执行计划跑偏的风险
    3.1 此表存储但是 User table 的 各表各列各索引的 top N 的统计数据,用来进行 执行计划的代价估算。可以观察相关 table id 后面的数据的变化情况,这些数据的变化反馈了你的数据变更情况。
    3.2 如果可以承担 执行计划跑偏的风险可以 truncate 这个 内部表让 tidb 对此数据进行重建。

如果对热点在意可以通过 调整 load base split 来缓解这一问题

3 个赞

一个表3-4万条统计信息 也太多了吧 是不是应该有一个清理机制

1 个赞

多不多 可以自己计算下

(行数+索引数量)* top_n* 分区数量
top_N 默认 20 最大 1024

1 个赞

有清理机制的,不用的 TopN 会被清理掉;
可以按照楼上的公式先算一下,看看是否合理;
另外可以关注下 tidb_analyze_version 这个变量,如果是 2 的话,那 TopN 的默认大小为 500,否则一般是 20;

1 个赞

show variables like ‘tidb_analyze_version’;
±---------------------±------+
| Variable_name | Value |
±---------------------±------+
| tidb_analyze_version | 2 |
select @@top_N;
ERROR 1193 (HY000): Unknown system variable ‘top_n’
top_n 的参数值怎么看?

大量 的table_id 都是不存在
select * from TABLES where TIDB_TABLE_ID=66406;
Empty set (1.21 sec)
select * from TABLES where TIDB_TABLE_ID=20132;
Empty set (1.48 sec)
select * from TABLES where TIDB_TABLE_ID=25042;
Empty set (2.37 sec)

(user:tidbdba time: 10:10)[db: information_schema]select * from TABLES where TIDB_TABLE_ID=67653;
| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | TABLE_TYPE | ENGINE | VERSION | ROW_FORMAT | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH | MAX_DATA_LENGTH | INDEX_LENGTH | DATA_FREE | AUTO_INCREMENT | CREATE_TIME | UPDATE_TIME | CHECK_TIME | TABLE_COLLATION | CHECKSUM | CREATE_OPTIONS | TABLE_COMMENT | TIDB_TABLE_ID | TIDB_ROW_ID_SHARDING_INFO | TIDB_PK_TYPE |
| def | yixintui_operate | gdt_account_daily_report_request_part | BASE TABLE | InnoDB | 10 | Compact | 4986 | 2357 | 11756923 | 0 | 109627 | 0 | NULL | 2022-01-05 15:53:09 | NULL | NULL | utf8mb4_bin | NULL | | 广点通部分账户日报表-请求时间 | 67653 | SHARD_BITS=4 | NONCLUSTERED |

1 个赞

gdt_account_daily_report_request_part 这个表也不是分区表 记录也只有4000多条
PRIMARY KEY (account_id,date) /*T![clustered_index] NONCLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T! SHARD_ROW_ID_BITS=4 PRE_SPLIT_REGIONS=2 */ COMMENT=‘部分账户日报表-请求时间’
select count(1) from yixintui_operate.gdt_account_daily_report_request_part ;
| count(1) |
| 4987 |

1 个赞

如果 analyze_version = 2 的话,默认的 TopN 搜集个数就是 500 个;
然后对于一个表,则一共有 (列数+索引数)*500,所以如果表比较宽和索引比较多的话,是会比较多。

目前在 v5.2 上的解决办法会比较 “手工” 一点;
需要自己用脚本,定期执行 analyze table with 50 topn 来减少 TopN 的搜集个数。

在 v5.4 后解决这个问题会更方便,执行一次 analyze table with 50 topn 后,TiDB 则会把 analyze 配置记录下来,后续一直用这个配置:
https://github.com/pingcap/docs-cn/blob/master/statistics.md#analyze-配置持久化

2 个赞

好的 ,那就只能等5.4 ? 没有系统参数设置 topN 是吧

1 个赞

是的,目前是没有办法;
如果一定要解决的话,有一个相对麻烦一点的方式是,把 auto-analyze 关闭,然后自己用脚本定期执行 “analyze table with xxx topn”;

1 个赞

这个就没有一个定期清理的机制吗?

5.4 已上线,可以去看看~

1 个赞

赞5.4

好的 。

1 个赞

此话题已在最后回复的 1 分钟后被自动关闭。不再允许新回复。