读性能慢-慢语句

慢日志获取

通过 Dashboard 获取慢语句 (v4.0 新功能)

在 TiDB 4.0 及后续版本中为了让 TiDB 运维更直观提供了 Dashboard 功能。通过查询 SQL语句分析 与 慢查询 页面即可快速了解当前的 慢 SQL 现状
参考链接:慢查询页面执行语句分析

通过查询日志

  • TiDB slow log
    在每个 TiDB 节点的 部署目录中默认会记录大于 300ms 的 SQL,默认记录到 tidb-slow.log 文件中。可以通过查看分析此文件了解此 TiDB 实例上执行过的慢语句。
    参考链接:慢日志查询
    P.S 此慢语句为当前实例慢语句,并非全局慢语句

  • expensive query
    TiDB 会将执行时间超过 tidb_expensive_query_time_threshold 限制(默认值为 60s),或使用内存超过 mem-quota-query 限制(默认值为 1 GB)的语句输出到 tidb-server 日志文件(默认文件为 “tidb.log”)中,用于在语句执行结束前定位消耗系统资源多的查询语句(以下简称为 expensive query),帮助用户分析和解决语句执行的性能问题。
    参考链接:定位消息系统资源多的查询

通过查询视图获取

  • 通过查询 information.slow_query 表,获取当前 TiDB 实例慢语句

  • 通过查询 information.cluster_slow_query 表,获取整个集群的慢语句 P.S 视图是通过解析对应的 slowlog 文件,强烈建议指定时间范围

  • 参考链接:SLOW_QUERY通过 SLOW_QUERY 表快速确认慢语句

通过 statment summary tables 获取更详尽的 SQL 记录

为了提供更为详尽的 SQL 执行记录,TiDB作为兼容 MySQL 的分布式数据库同样提供了一系列 statment summary tables,通过此系列表可以查询更丰富全面的 SQL 执行记录,并对历史执行情况进行统计分析
P.S 默认保留 12 小时的 statment 记录
参考链接:SQL 语句统计定位慢查询

统计信息

产生慢语句有很多种原因最常见的是,因为执行计划不准确导致的执行计划选错,或本身因为代码设计限制导致选错了执行计划下面分别说明

原因

统计信息的收集默认是自动进行的。自动收集需要满足两类条件

新表行数达到 1000,且 1 分钟内没有更新

表的(修改数/当前总行数)大于 tidb_auto_analyze_ratio 默认是 0.5 的时候,并且当前时间在 tidb_auto_analyze_start_time、tidb_auto_analyze_end_time 时间范围内(Time 时间使用的 UTC时间)会自动触发 analyze 语句

当表更新量很大或者表本身很大,还并为达到 auto analyze 的阈值,很有可能导致统计信息不准确的,从而执行优化器制定了错误的执行计划。导致慢语句的产生

问题定位

通过如下命令查询表的健康度,一般如果健康度低于 70%就建议进行手动的统计信息收集。通过如下命令可以快速查看对应表的健康度

SHOW STATS_HEALTHY [ShowLikeOrWhere];

通过如下命令查询表统计信息源数据,当 modify_count >= row_count 时,健康度为 0;当 modify_count < row_count 时,健康度为 (1 - modify_count/row_count) * 100

SHOW STATS_META [ShowLikeOrWhere];

表的基础行数越大,健康度百分比越容易失真,更新频繁的表建议定期进行手动统计信息收集

解决方法

注意:在重新收集统计信息之前建议先 Dump 下统计信息,以及对应的表结构,方便对问题的具体定位。或在新版本中校验问题是否得到有效解决

统计信息 Dump
通过以下接口可以获取数据库 ${db_name} 中的表 ${table_name} 的 json 格式的统计信息

http://${tidb-server-ip}:${tidb-server-status-port}/stats/dump/${db_name}/${table_name}

手动收集统计信息

ANALYZE TABLE TableNameList [ WITH NUM BUCKETS TOPN CMSKETCH DEPTH CMSKETCH WIDTH SAMPLES];

参考资料

统计信息简介

执行计划

导致执行计划错误的原因,除了统计信息不准确外,还有一些比较常见的问题。

问题定位(需要掌握数据库索引相关基础知识)

我们可以通过 ExplainExplain Analyze 来获取 SQL 具体的执行计划。 Explain 为 TiDB 估算的统计信息,Explain Analyze还包含了 SQL 语句实际执行的相关信息。我们通过SQL 语句,及其执行计划再结合对应的表结构进行具体的问题分析与定位。

解决办法

  • 错误选择索引\重复索引 问题
    由于表中包含多个重复索引 如 Index_A(a,b) 与 Index_B(a,b,c)及为重复索引
    对于等值查询,错误索引可能是由 Count-Min Sketch 引起的。这时可以先检查是不是这种特殊情况,然后进行对应的处理。

  • 使用了不合适的 Join 算子
    Hash Join\ Merge Join\ Index Join 优化器默认会选择一个它认为最优秀的,但有可能选错。原因需要具体分析表结构、执行计划、统计信息以及确认 TiDB 版本。

  • 某些场景下用 Tiflash 不一定优于 TiKV
    TiFlash 时候大数据统计、大表与小表的关联查询。如果查明细数据不一定 Tiflash 更优。通过 TPCC-H 测试也可以发现 TiFlash 并不是所有场景都优于 TiKV

解决方法(以上问题均通过此方法进行解决)

测试使用 Optimizer Hint 改写执行计划

使用 SPM 绑定改写的 SQL 语句

统计信息 Dump,并将相关表结构与 Dump 的统计信息,发送到 Asktug 寻求官方帮助

如必要,可通过优化表结构、SQL 语句或业务实现,进一步解决问题

P.S:关于 SPM 的使用 可以参考 执行计划管理

其他问题

SQL 执行的并发度不足

在 OLAP 场景下,我们需要查询大量数据需要进行聚合统计分析,此时 TiDB 默认的算子并发度会偏保守,需要我们手动调整相应的参数。

聚合函数的优化

在 TP 场景为了提升并发度一般推荐采用 stream agg 算子进行 聚合统计。但在 AP 场景 更适合使用 hash agg 进行多并发的数据统计,可有效提升聚合函数的效率,并且通过加大 hashagg 算子的并发线程数还可以进一步提升效率。

超范围数据的估算错误

在之前的 TiDB 版本,当查询值不在统计信息 bucket 的 最小值与最大值的范围内,就会导致估算的选择率大大超出了预期,尤其在表的数据更新非常少的场景下,这个估算结果的偏差会更加严重

MVCC 旧版本过多

在日常使用 TiDB 时候为了防止数据误删除,我们会把 GC Life time 设置一个比较长的时间,譬如 24H。由于目前此设置是一个全局设置,在某些表更新非常频繁的情况情况下就会有大量的 MVCC 比较旧的版本存在,如果版本过多会对查询性能有较大影响

  • 问题定位
    通过查看 slow query 或 statment summary 表中 Processed ed Keys 与 Total Keys 的值 。与 total keys 相比,processed keys 不包含 MVCC 的旧版本。如果 processed keys 和 total keys 相差很大,说明旧版本比较多。

  • 解决办法
    调整 GC Life Time 到一个比较合理的时间范围,未来有计划根据不同的表设置不同的 GC Life Time

感谢分享