diff --git a/dev/TOC.md b/dev/TOC.md index 0f4a9f264583..5fc49ed57cc4 100644 --- a/dev/TOC.md +++ b/dev/TOC.md @@ -320,6 +320,7 @@ - [统计信息概述](/dev/reference/performance/statistics.md) - [Optimizer Hints](/dev/reference/performance/optimizer-hints.md) - [使用 SQL 语句检查 TiDB 集群状态](/dev/reference/performance/check-cluster-status-using-sql-statements.md) + - [Statement Summary Table](/dev/reference/performance/statement-summary.md) - [TiKV 调优](/dev/reference/performance/tune-tikv.md) - [TiDB 最佳实践](https://pingcap.com/blog-cn/tidb-best-practice/) + [TiSpark 使用指南](/dev/reference/tispark.md) diff --git a/dev/reference/configuration/tidb-server/configuration-file.md b/dev/reference/configuration/tidb-server/configuration-file.md index d17830e3b1db..46ff43f9872c 100644 --- a/dev/reference/configuration/tidb-server/configuration-file.md +++ b/dev/reference/configuration/tidb-server/configuration-file.md @@ -390,3 +390,17 @@ TiDB 服务状态相关配置。 + 输与 database 相关的 QPS metrics 到 promethus的开关。 + 默认值:false + +## stmt-summary 从 v3.0.4 版本开始引入 + +系统表 `events_statement_summary_by_digest` 的相关配置。 + +### max-stmt-count + ++ `events_statement_summary_by_digest` 表中保存的 SQL 种类的最大数量。 ++ 默认值:100 + +### max-sql-length + ++ `events_statement_summary_by_digest` 表中`DIGEST_TEXT` 和 `QUERY_SAMPLE_TEXT` 列的最大显示长度。 ++ 默认值:4096 diff --git a/dev/reference/configuration/tidb-server/tidb-specific-variables.md b/dev/reference/configuration/tidb-server/tidb-specific-variables.md index 586dc2a7c8f4..19bd257d7757 100644 --- a/dev/reference/configuration/tidb-server/tidb-specific-variables.md +++ b/dev/reference/configuration/tidb-server/tidb-specific-variables.md @@ -688,3 +688,11 @@ TiDB 默认会在建表时为新表分裂 Region。开启该变量后,会在 默认值:0 这个变量用来控制是否允许通过 `ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE` 来移除某个列的 `auto_increment` 属性。默认为不允许。 + +### tidb_enable_stmt_summary 从 v3.0.4 版本开始引入 + +作用域:SESSION | GLOBAL + +默认值:0 + +这个变量用来控制是否开启 statement summary 功能。如果开启,SQL 的耗时等执行信息将被记录到系统表 `performance_schema.events_statement_summary_by_digest` 中,用于定位和排查 SQL 性能问题。 diff --git a/dev/reference/mysql-compatibility.md b/dev/reference/mysql-compatibility.md index b95734979163..5522d40a03d2 100644 --- a/dev/reference/mysql-compatibility.md +++ b/dev/reference/mysql-compatibility.md @@ -69,6 +69,8 @@ TiDB 实现自增 ID 的原理是每个 tidb-server 实例缓存一段 ID 值用 Performance schema 表在 TiDB 中返回结果为空。TiDB 使用 [Prometheus 和 Grafana](/dev/how-to/monitor/monitor-a-cluster.md) 来监测性能指标。 +从 TiDB 3.0.4 版本开始,TiDB 支持 `events_statements_summary_by_digest`,参见 [Statement Summary Table](/dev/reference/performance/statement-summary.md)。 + ### 查询计划 TiDB 的查询计划(`EXPLAIN`/`EXPLAIN FOR`)输出格式与 MySQL 差别较大,同时 `EXPLAIN FOR` 的输出内容与权限设置与 MySQL 不一致,参见[理解 TiDB 执行计划](/dev/reference/performance/understanding-the-query-execution-plan.md)。 diff --git a/dev/reference/performance/statement-summary.md b/dev/reference/performance/statement-summary.md new file mode 100644 index 000000000000..e3ff42f9204f --- /dev/null +++ b/dev/reference/performance/statement-summary.md @@ -0,0 +1,148 @@ +--- +title: Statement Summary Table +category: reference +--- + +# Statement Summary Table + +针对 SQL 性能相关的问题,MySQL 在 `performance_schema` 提供了 [statement summary tables](https://dev.mysql.com/doc/refman/5.6/en/statement-summary-tables.html),用来监控和统计 SQL。例如其中的一张表 `events_statements_summary_by_digest`,提供了丰富的字段,包括延迟、执行次数、扫描行数、全表扫描次数等,有助于用户定位 SQL 问题。 + +为此,从 3.0.4 版本开始,TiDB 也提供系统表 `events_statements_summary_by_digest`。本文将详细介绍 `events_statements_summary_by_digest`,以及如何利用它来排查 SQL 性能问题。 + +## events_statements_summary_by_digest 介绍 + +`events_statement_summary_by_digest` 是 `performance_schema` 里的一张系统表。顾名思义,它把 SQL 按 digest 分组,统计每一组的 SQL 信息。 + +此处的 digest 与 slow log 里的 digest 一样,是把 SQL 规范化后算出的唯一标识符。 +SQL 的规范化会忽略常量、空白符、大小写的差别。也就是说,只要语法一致,就会归到同一类。 + +例如: + +```sql +SELECT * FROM employee WHERE id IN (1, 2, 3) AND salary BETWEEN 1000 AND 2000; +select * from EMPLOYEE where ID in (4, 5) and SALARY between 3000 and 4000; +``` + +规范化后都是: + +```sql +select * from employee where id in (...) and salary between ? and ?; +``` + +接下来详细看一下 `events_statements_summary_by_digest` 的表结构。 +因为 TiDB 中的很多概念不同于 MySQL,所以 `events_statements_summary_by_digest` 也与 MySQL 有一些区别。 + +查询 `events_statements_summary_by_digest` 的输出示例: + +``` + SCHEMA_NAME: test + DIGEST: 0611cc2fe792f8c146cc97d39b31d9562014cf15f8d41f23a4938ca341f54182 + DIGEST_TEXT: select * from employee where id = ? + EXEC_COUNT: 3 + SUM_LATENCY: 1035161 + MAX_LATENCY: 399594 + MIN_LATENCY: 301353 + AVG_LATENCY: 345053 +SUM_ROWS_AFFECTED: 0 + FIRST_SEEN: 2019-09-12 18:47:14 + LAST_SEEN: 2019-09-12 18:47:16 +QUERY_SAMPLE_TEXT: select * from employee where id=3100 +``` + +以下是各个字段的含义: + +| 列名 | 含义 | +|:----------------- |:-------------------------------- | +| SCHEMA_NAME | 执行这类 SQL 的当前 schema | +| DIGEST | SQL 的 digest | +| DIGEST_TEXT | 规范化后的 SQL | +| EXEC_COUNT | 这类 SQL 执行的总次数 | +| SUM_LATENCY | 这类 SQL 执行的总延迟,单位 ns | +| MAX_LATENCY | 这类 SQL 执行的最大延迟,单位 ns | +| MIN_LATENCY | 这类 SQL 执行的最小延迟,单位 ns | +| AVG_LATENCY | 这类 SQL 执行的平均延迟,单位 ns | +| SUM_ROWS_AFFECTED | 这类 SQL 的总影响行数 | +| FIRST_SEEN | 这类 SQL 第一次执行的时间 | +| LAST_SEEN | 这类 SQL 最后一次执行的时间 | +| QUERY_SAMPLE_TEXT | 这类 SQL 首次出现的原 SQL 语句 | + +## 排查示例 + +下面用两个示例问题演示如何利用 statement summary 来排查。 + +### SQL 延迟比较大,是不是服务端的问题? + +例如客户端显示 employee 表的点查比较慢,那么可以按 SQL 文本来模糊查询: + +```sql +SELECT avg_latency, exec_count, query_sample_text + FROM performance_schema.events_statements_summary_by_digest + WHERE digest_text LIKE ‘select * from employee%’; +``` + +结果如下,`avg_latency` 是 1 ms 和 0.3 ms,在正常范围,所以可以判定不是服务端的问题,继而排查客户端或网络问题。 + +``` ++-------------+------------+------------------------------------------+ +| avg_latency | exec_count | query_sample_text | ++-------------+------------+------------------------------------------+ +| 1042040 | 2 | select * from employee where name='eric' | +| 345053 | 3 | select * from employee where id=3100 | ++-------------+------------+------------------------------------------+ +2 rows in set (0.00 sec) +``` + +### 哪类 SQL 的总耗时最高? + +如果要对系统调优,可以找出耗时最高的 3 类 SQL: + +```sql +SELECT sum_latency, avg_latency, exec_count, query_sample_text + FROM performance_schema.events_statements_summary_by_digest + ORDER BY sum_latency DESC LIMIT 3; +``` + +结果显示以下三类 SQL 的总延迟最高,所以这些 SQL 需要重点优化。 + +``` ++-------------+-------------+------------+-----------------------------------------------------------------------+ +| sum_latency | avg_latency | exec_count | query_sample_text | ++-------------+-------------+------------+-----------------------------------------------------------------------+ +| 7855660 | 1122237 | 7 | select avg(salary) from employee where company_id=2013 | +| 7241960 | 1448392 | 5 | select * from employee join company on employee.company_id=company.id | +| 2084081 | 1042040 | 2 | select * from employee where name='eric' | ++-------------+-------------+------------+-----------------------------------------------------------------------+ +3 rows in set (0.00 sec) +``` + +## 参数配置 + +statement summary 功能默认关闭,通过设置系统变量打开,例如: + +```sql +set global tidb_enable_stmt_summary = true; +``` + +`tidb_enable_stmt_summary` 有 global 和 session 两种作用域,它们的生效方式与其他系统变量不一样: + +- 设置 global 变量后整个集群立即生效 +- 设置 session 变量后当前 TiDB-Server 立即生效,这对于调试单个 TiDB-Server 比较有用 +- 优先读 session 变量,没有设置过 session 变量才会读 global 变量 +- 把 session 变量设为空字符串,将会重新读 global 变量 + +statement summary 关闭后,系统表里的数据会被清空,下次打开后重新统计。经测试,打开后对性能几乎没有影响。 + +由于 `events_statements_summary_by_digest` 是内存表,为了防止内存问题,需要限制保存的 SQL 条数和 SQL 的最大显示长度。这两个参数都在 config.toml 的 [stmt-summary] 类别下配置: + +- 通过 `max-stmt-count` 更改保存的 SQL 种类数量,默认 100 条。当 SQL 种类超过 `max-stmt-count` 时,会移除最近没有使用的 SQL。 +- 通过 `max-sql-length` 更改 `DIGEST_TEXT` 和 `QUERY_SAMPLE_TEXT` 的最大显示长度,默认是 4096。 + +这两个参数建议根据实际情况调整,不宜设置得过大。 + +## 目前的限制 + +`events_statements_summary_by_digest` 现在还存在一些限制: + +- 查询 `events_statements_summary_by_digest` 时,只会显示当前 TiDB-Server 的 statement summary,而不是整个集群的 statement summary。 +- statement summary 不会滚动更新。一旦 `tidb_enable_stmt_summary` 打开,SQL 信息就开始统计。随着时间的推移,statement summary 累加,所以无法查看最近一段时间内的 statement summary。所以最佳实践是,需要排查问题的时候再打开,查看一段时间内的 statement summary。 +- TiDB Server 重启后 statement summary 丢失。因为 `events_statements_summary_by_digest` 是内存表,不会持久化数据,所以一旦 Server 被重启,statement summary 随之丢失。 diff --git a/v3.0/TOC.md b/v3.0/TOC.md index c91109387511..725c4dba2c54 100644 --- a/v3.0/TOC.md +++ b/v3.0/TOC.md @@ -321,6 +321,7 @@ - [统计信息概述](/v3.0/reference/performance/statistics.md) - [Optimizer Hints](/v3.0/reference/performance/optimizer-hints.md) - [使用 SQL 语句检查 TiDB 集群状态](/v3.0/reference/performance/check-cluster-status-using-sql-statements.md) + - [Statement Summary Table](/v3.0/reference/performance/statement-summary.md) - [TiKV 调优](/v3.0/reference/performance/tune-tikv.md) - [TiDB 最佳实践](https://pingcap.com/blog-cn/tidb-best-practice/) + [TiSpark 使用指南](/v3.0/reference/tispark.md) diff --git a/v3.0/reference/configuration/tidb-server/configuration-file.md b/v3.0/reference/configuration/tidb-server/configuration-file.md index d1440149abe9..07262cd3336c 100644 --- a/v3.0/reference/configuration/tidb-server/configuration-file.md +++ b/v3.0/reference/configuration/tidb-server/configuration-file.md @@ -391,3 +391,17 @@ TiDB 服务状态相关配置。 + 输与 database 相关的 QPS metrics 到 promethus的开关。 + 默认值:false + +## stmt-summary 从 v3.0.4 版本开始引入 + +系统表 `events_statement_summary_by_digest` 的相关配置。 + +### max-stmt-count + ++ `events_statement_summary_by_digest` 表中保存的 SQL 种类的最大数量。 ++ 默认值:100 + +### max-sql-length + ++ `events_statement_summary_by_digest` 表中`DIGEST_TEXT` 和 `QUERY_SAMPLE_TEXT` 列的最大显示长度。 ++ 默认值:4096 diff --git a/v3.0/reference/configuration/tidb-server/tidb-specific-variables.md b/v3.0/reference/configuration/tidb-server/tidb-specific-variables.md index 8f7b3c9d28d6..1777fd8ea6d9 100644 --- a/v3.0/reference/configuration/tidb-server/tidb-specific-variables.md +++ b/v3.0/reference/configuration/tidb-server/tidb-specific-variables.md @@ -690,3 +690,11 @@ TiDB 默认会在建表时为新表分裂 Region。开启该变量后,会在 默认值:0 这个变量用来控制是否允许通过 `ALTER TABLE MODIFY` 或 `ALTER TABLE CHANGE` 来移除某个列的 `auto_increment` 属性。默认为不允许。 + +### tidb_enable_stmt_summary 从 v3.0.4 版本开始引入 + +作用域:SESSION | GLOBAL + +默认值:0 + +这个变量用来控制是否开启 statement summary 功能。如果开启,SQL 的耗时等执行信息将被记录到系统表 `performance_schema.events_statement_summary_by_digest` 中,用于定位和排查 SQL 性能问题。 diff --git a/v3.0/reference/mysql-compatibility.md b/v3.0/reference/mysql-compatibility.md index fc852c29b749..9ddbaa35475e 100644 --- a/v3.0/reference/mysql-compatibility.md +++ b/v3.0/reference/mysql-compatibility.md @@ -69,6 +69,8 @@ TiDB 实现自增 ID 的原理是每个 tidb-server 实例缓存一段 ID 值用 Performance schema 表在 TiDB 中返回结果为空。TiDB 使用 [Prometheus 和 Grafana](/v3.0/how-to/monitor/monitor-a-cluster.md) 来监测性能指标。 +从 TiDB 3.0.4 版本开始,TiDB 支持 `events_statements_summary_by_digest`,参见 [Statement Summary Table](/v3.0/reference/performance/statement-summary.md)。 + ### 查询计划 TiDB 的查询计划(`EXPLAIN`/`EXPLAIN FOR`)输出格式与 MySQL 差别较大,同时 `EXPLAIN FOR` 的输出内容与权限设置与 MySQL 不一致,参见[理解 TiDB 执行计划](/v3.0/reference/performance/understanding-the-query-execution-plan.md)。 diff --git a/v3.0/reference/performance/statement-summary.md b/v3.0/reference/performance/statement-summary.md new file mode 100644 index 000000000000..e3ff42f9204f --- /dev/null +++ b/v3.0/reference/performance/statement-summary.md @@ -0,0 +1,148 @@ +--- +title: Statement Summary Table +category: reference +--- + +# Statement Summary Table + +针对 SQL 性能相关的问题,MySQL 在 `performance_schema` 提供了 [statement summary tables](https://dev.mysql.com/doc/refman/5.6/en/statement-summary-tables.html),用来监控和统计 SQL。例如其中的一张表 `events_statements_summary_by_digest`,提供了丰富的字段,包括延迟、执行次数、扫描行数、全表扫描次数等,有助于用户定位 SQL 问题。 + +为此,从 3.0.4 版本开始,TiDB 也提供系统表 `events_statements_summary_by_digest`。本文将详细介绍 `events_statements_summary_by_digest`,以及如何利用它来排查 SQL 性能问题。 + +## events_statements_summary_by_digest 介绍 + +`events_statement_summary_by_digest` 是 `performance_schema` 里的一张系统表。顾名思义,它把 SQL 按 digest 分组,统计每一组的 SQL 信息。 + +此处的 digest 与 slow log 里的 digest 一样,是把 SQL 规范化后算出的唯一标识符。 +SQL 的规范化会忽略常量、空白符、大小写的差别。也就是说,只要语法一致,就会归到同一类。 + +例如: + +```sql +SELECT * FROM employee WHERE id IN (1, 2, 3) AND salary BETWEEN 1000 AND 2000; +select * from EMPLOYEE where ID in (4, 5) and SALARY between 3000 and 4000; +``` + +规范化后都是: + +```sql +select * from employee where id in (...) and salary between ? and ?; +``` + +接下来详细看一下 `events_statements_summary_by_digest` 的表结构。 +因为 TiDB 中的很多概念不同于 MySQL,所以 `events_statements_summary_by_digest` 也与 MySQL 有一些区别。 + +查询 `events_statements_summary_by_digest` 的输出示例: + +``` + SCHEMA_NAME: test + DIGEST: 0611cc2fe792f8c146cc97d39b31d9562014cf15f8d41f23a4938ca341f54182 + DIGEST_TEXT: select * from employee where id = ? + EXEC_COUNT: 3 + SUM_LATENCY: 1035161 + MAX_LATENCY: 399594 + MIN_LATENCY: 301353 + AVG_LATENCY: 345053 +SUM_ROWS_AFFECTED: 0 + FIRST_SEEN: 2019-09-12 18:47:14 + LAST_SEEN: 2019-09-12 18:47:16 +QUERY_SAMPLE_TEXT: select * from employee where id=3100 +``` + +以下是各个字段的含义: + +| 列名 | 含义 | +|:----------------- |:-------------------------------- | +| SCHEMA_NAME | 执行这类 SQL 的当前 schema | +| DIGEST | SQL 的 digest | +| DIGEST_TEXT | 规范化后的 SQL | +| EXEC_COUNT | 这类 SQL 执行的总次数 | +| SUM_LATENCY | 这类 SQL 执行的总延迟,单位 ns | +| MAX_LATENCY | 这类 SQL 执行的最大延迟,单位 ns | +| MIN_LATENCY | 这类 SQL 执行的最小延迟,单位 ns | +| AVG_LATENCY | 这类 SQL 执行的平均延迟,单位 ns | +| SUM_ROWS_AFFECTED | 这类 SQL 的总影响行数 | +| FIRST_SEEN | 这类 SQL 第一次执行的时间 | +| LAST_SEEN | 这类 SQL 最后一次执行的时间 | +| QUERY_SAMPLE_TEXT | 这类 SQL 首次出现的原 SQL 语句 | + +## 排查示例 + +下面用两个示例问题演示如何利用 statement summary 来排查。 + +### SQL 延迟比较大,是不是服务端的问题? + +例如客户端显示 employee 表的点查比较慢,那么可以按 SQL 文本来模糊查询: + +```sql +SELECT avg_latency, exec_count, query_sample_text + FROM performance_schema.events_statements_summary_by_digest + WHERE digest_text LIKE ‘select * from employee%’; +``` + +结果如下,`avg_latency` 是 1 ms 和 0.3 ms,在正常范围,所以可以判定不是服务端的问题,继而排查客户端或网络问题。 + +``` ++-------------+------------+------------------------------------------+ +| avg_latency | exec_count | query_sample_text | ++-------------+------------+------------------------------------------+ +| 1042040 | 2 | select * from employee where name='eric' | +| 345053 | 3 | select * from employee where id=3100 | ++-------------+------------+------------------------------------------+ +2 rows in set (0.00 sec) +``` + +### 哪类 SQL 的总耗时最高? + +如果要对系统调优,可以找出耗时最高的 3 类 SQL: + +```sql +SELECT sum_latency, avg_latency, exec_count, query_sample_text + FROM performance_schema.events_statements_summary_by_digest + ORDER BY sum_latency DESC LIMIT 3; +``` + +结果显示以下三类 SQL 的总延迟最高,所以这些 SQL 需要重点优化。 + +``` ++-------------+-------------+------------+-----------------------------------------------------------------------+ +| sum_latency | avg_latency | exec_count | query_sample_text | ++-------------+-------------+------------+-----------------------------------------------------------------------+ +| 7855660 | 1122237 | 7 | select avg(salary) from employee where company_id=2013 | +| 7241960 | 1448392 | 5 | select * from employee join company on employee.company_id=company.id | +| 2084081 | 1042040 | 2 | select * from employee where name='eric' | ++-------------+-------------+------------+-----------------------------------------------------------------------+ +3 rows in set (0.00 sec) +``` + +## 参数配置 + +statement summary 功能默认关闭,通过设置系统变量打开,例如: + +```sql +set global tidb_enable_stmt_summary = true; +``` + +`tidb_enable_stmt_summary` 有 global 和 session 两种作用域,它们的生效方式与其他系统变量不一样: + +- 设置 global 变量后整个集群立即生效 +- 设置 session 变量后当前 TiDB-Server 立即生效,这对于调试单个 TiDB-Server 比较有用 +- 优先读 session 变量,没有设置过 session 变量才会读 global 变量 +- 把 session 变量设为空字符串,将会重新读 global 变量 + +statement summary 关闭后,系统表里的数据会被清空,下次打开后重新统计。经测试,打开后对性能几乎没有影响。 + +由于 `events_statements_summary_by_digest` 是内存表,为了防止内存问题,需要限制保存的 SQL 条数和 SQL 的最大显示长度。这两个参数都在 config.toml 的 [stmt-summary] 类别下配置: + +- 通过 `max-stmt-count` 更改保存的 SQL 种类数量,默认 100 条。当 SQL 种类超过 `max-stmt-count` 时,会移除最近没有使用的 SQL。 +- 通过 `max-sql-length` 更改 `DIGEST_TEXT` 和 `QUERY_SAMPLE_TEXT` 的最大显示长度,默认是 4096。 + +这两个参数建议根据实际情况调整,不宜设置得过大。 + +## 目前的限制 + +`events_statements_summary_by_digest` 现在还存在一些限制: + +- 查询 `events_statements_summary_by_digest` 时,只会显示当前 TiDB-Server 的 statement summary,而不是整个集群的 statement summary。 +- statement summary 不会滚动更新。一旦 `tidb_enable_stmt_summary` 打开,SQL 信息就开始统计。随着时间的推移,statement summary 累加,所以无法查看最近一段时间内的 statement summary。所以最佳实践是,需要排查问题的时候再打开,查看一段时间内的 statement summary。 +- TiDB Server 重启后 statement summary 丢失。因为 `events_statements_summary_by_digest` 是内存表,不会持久化数据,所以一旦 Server 被重启,statement summary 随之丢失。