Skip to content

Commit

Permalink
Merge pull request #1939 from djshow832/add_stmt_summary_docs
Browse files Browse the repository at this point in the history
reference: add documentation for statement summary
  • Loading branch information
dcalvin authored Oct 14, 2019
2 parents 2938fd8 + 5378737 commit 0a1a875
Show file tree
Hide file tree
Showing 10 changed files with 346 additions and 0 deletions.
1 change: 1 addition & 0 deletions dev/TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 14 additions & 0 deletions dev/reference/configuration/tidb-server/configuration-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,17 @@ TiDB 服务状态相关配置。

+ 输与 database 相关的 QPS metrics 到 promethus的开关。
+ 默认值:false

## stmt-summary <span class="version-mark">从 v3.0.4 版本开始引入</span>

系统表 `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
Original file line number Diff line number Diff line change
Expand Up @@ -688,3 +688,11 @@ TiDB 默认会在建表时为新表分裂 Region。开启该变量后,会在
默认值:0

这个变量用来控制是否允许通过 `ALTER TABLE MODIFY``ALTER TABLE CHANGE` 来移除某个列的 `auto_increment` 属性。默认为不允许。

### tidb_enable_stmt_summary <span class="version-mark">从 v3.0.4 版本开始引入</span>

作用域:SESSION | GLOBAL

默认值:0

这个变量用来控制是否开启 statement summary 功能。如果开启,SQL 的耗时等执行信息将被记录到系统表 `performance_schema.events_statement_summary_by_digest` 中,用于定位和排查 SQL 性能问题。
2 changes: 2 additions & 0 deletions dev/reference/mysql-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
148 changes: 148 additions & 0 deletions dev/reference/performance/statement-summary.md
Original file line number Diff line number Diff line change
@@ -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 LIKEselect * 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 随之丢失。
1 change: 1 addition & 0 deletions v3.0/TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 14 additions & 0 deletions v3.0/reference/configuration/tidb-server/configuration-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,17 @@ TiDB 服务状态相关配置。

+ 输与 database 相关的 QPS metrics 到 promethus的开关。
+ 默认值:false

## stmt-summary <span class="version-mark">从 v3.0.4 版本开始引入</span>

系统表 `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
Original file line number Diff line number Diff line change
Expand Up @@ -690,3 +690,11 @@ TiDB 默认会在建表时为新表分裂 Region。开启该变量后,会在
默认值:0

这个变量用来控制是否允许通过 `ALTER TABLE MODIFY``ALTER TABLE CHANGE` 来移除某个列的 `auto_increment` 属性。默认为不允许。

### tidb_enable_stmt_summary <span class="version-mark">从 v3.0.4 版本开始引入</span>

作用域:SESSION | GLOBAL

默认值:0

这个变量用来控制是否开启 statement summary 功能。如果开启,SQL 的耗时等执行信息将被记录到系统表 `performance_schema.events_statement_summary_by_digest` 中,用于定位和排查 SQL 性能问题。
2 changes: 2 additions & 0 deletions v3.0/reference/mysql-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
148 changes: 148 additions & 0 deletions v3.0/reference/performance/statement-summary.md
Original file line number Diff line number Diff line change
@@ -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 LIKEselect * 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 随之丢失。

0 comments on commit 0a1a875

Please sign in to comment.