## 27.10 性能模式语句摘要和抽样

MySQL 服务器能够维护语句摘要信息。摘要过程将每个 SQL 语句转换为规范化形式（语句摘要），并根据规范化结果计算 SHA-256 哈希值（摘要哈希值）。规范化允许对相似的语句进行分组和汇总，以公开有关服务器正在执行的语句类型及其发生频率的信息。对于每个摘要，将生成摘要的代表性语句存储为样本。本节描述语句摘要和采样是如何发生的以及它们如何有用。

无论性能模式是否可用，解析器都会进行摘要，因此 MySQL 企业防火墙和查询重写插件等其他功能可以访问语句摘要。

-   [声明文摘一般概念](performance-schema-statement-digests.html#statement-digests-general)

-   [性能模式中的语句摘要](performance-schema-statement-digests.html#statement-digests-performance-schema)

-   [语句摘要内存使用](performance-schema-statement-digests.html#statement-digests-memory-use)

-   [语句抽样](performance-schema-statement-digests.html#statement-digests-sampling)

### 声明文摘一般概念

当解析器收到一条 SQL 语句时，如果需要该摘要，它会计算一个语句摘要，如果以下任何条件为真，则该摘要为真：

-   性能模式摘要检测已启用

-   MySQL 企业防火墙已启用

-   启用查询重写插件

    解析器也被[`STATEMENT_DIGEST_TEXT()`](encryption-functions.html#function_statement-digest-text)和[`STATEMENT_DIGEST()`](encryption-functions.html#function_statement-digest)函数，应用程序可以调用这些函数来分别从 SQL 语句计算规范化语句摘要和摘要哈希值。

    这[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)系统变量值确定每个会话可用于计算规范化语句摘要的最大字节数。一旦在摘要计算期间使用了该空间量，就会发生截断：不再收集已解析语句中的标记或计算其摘要值。仅在解析令牌的那么多字节之后才不同的语句产生相同的规范化语句摘要，并且如果比较或聚合摘要统计信息，则认为它们是相同的。

警告

设置[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)系统变量为零会禁用摘要生成，这也会禁用需要摘要的服务器功能。

在计算出规范化语句后，会从中计算出 SHA-256 哈希值。此外：

-   如果启用了 MySQL Enterprise Firewall，则会调用它并且计算的摘要可供它使用。

-   如果启用了任何查询重写插件，则会调用它，并且可以使用语句摘要和摘要值。

-   如果 Performance Schema 启用了摘要检测，它会制作规范化语句摘要的副本，最多分配[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)字节。因此，如果[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)小于[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length), 副本相对于原件被截断。规范化语句摘要的副本与从原始规范化语句计算的 SHA-256 哈希值一起存储在适当的性能模式表中。（如果性能模式相对于原始数据截断了规范化语句摘要的副本，它不会重新计算 SHA-256 哈希值。）

    语句规范化将语句文本转换为更标准化的摘要字符串表示，该表示保留了一般语句结构，同时删除了对结构不重要的信息：

-   保留对象标识符，例如数据库和表名。

-   文字值被转换为参数标记。规范化语句不保留姓名、密码、日期等信息。

-   删除注释并调整空格。

    考虑这些陈述：


```
SELECT * FROM orders WHERE customer_id=10 AND quantity>20
SELECT * FROM orders WHERE customer_id = 20 AND quantity > 100
```

为了规范化这些语句，解析器将数据值替换为`?`并调整空白。两个语句产生相同的规范化形式，因此被认为是“相同的”：

```
SELECT * FROM orders WHERE customer_id = ? AND quantity > ?
```

规范化的陈述包含较少的信息，但仍然代表原始陈述。其他具有不同数据值的类似语句具有相同的规范化形式。

现在考虑这些陈述：

```
SELECT * FROM customers WHERE customer_id = 1000
SELECT * FROM orders WHERE customer_id = 1000
```

在这种情况下，规范化语句不同，因为对象标识符不同：

```
SELECT * FROM customers WHERE customer_id = ?
SELECT * FROM orders WHERE customer_id = ?
```

如果规范化产生的语句超出了摘要缓冲区中的可用空间（由[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length))，会发生截断并且文本以“...”结尾。仅在“...”之后出现的部分不同的长规范化语句被认为是相同的。考虑这些陈述：

```
SELECT * FROM mytable WHERE cola = 10 AND colb = 20
SELECT * FROM mytable WHERE cola = 10 AND colc = 20
```

如果截止恰好在`和`, 两个语句都有这个规范化的形式：

```
SELECT * FROM mytable WHERE cola = ? AND ...
```

在这种情况下，第二列名称的差异将丢失，并且两个语句被认为是相同的。

### 性能模式中的语句摘要

在性能模式中，语句摘要涉及以下元素：

-   一种`statements_digest`消费者在[`setup_consumers`](performance-schema-setup-consumers-table.html)table 控制 Performance Schema 是否维护摘要信息。看[声明文摘消费者](performance-schema-consumer-filtering.html#performance-schema-consumer-filtering-statement-digest).

-   语句事件表（[`events_statements_current`](performance-schema-events-statements-current-table.html),[`events_statements_history`](performance-schema-events-statements-history-table.html)， 和[`events_statements_history_long`](performance-schema-events-statements-history-long-table.html)) 具有用于存储规范化语句摘要和相应摘要 SHA-256 哈希值的列：

    -   `DIGEST_TEXT`是规范化语句摘要的文本。这是原始规范化语句的副本，最大计算为[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)字节，根据需要进一步截断[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)字节。

    -   `消化`是从原始规范化语句计算的摘要 SHA-256 哈希值。

        看[第 27.12.6 节，“性能模式语句事件表”](performance-schema-statement-tables.html).

-   这[`events_statements_summary_by_digest`](performance-schema-statement-summary-tables.html)汇总表提供汇总的语句摘要信息。此表汇总了每个语句的信息`SCHEMA_NAME`和`消化`组合。性能模式使用 SHA-256 哈希值进行聚合，因为它们计算速度快，并且具有可最大限度减少冲突的有利统计分布。看[第 27.12.20.3 节，“报表汇总表”](performance-schema-statement-summary-tables.html).

    一些性能表有一个存储原始 SQL 语句的列，从中计算摘要：

-   这`SQL_TEXT`的列[`events_statements_current`](performance-schema-events-statements-current-table.html),[`events_statements_history`](performance-schema-events-statements-history-table.html)， 和[`events_statements_history_long`](performance-schema-events-statements-history-long-table.html)语句事件表。

-   这`QUERY_SAMPLE_TEXT`的列[`events_statements_summary_by_digest`](performance-schema-statement-summary-tables.html)汇总表。

    默认情况下，可用于语句显示的最大空间为 1024 字节。要更改此值，请设置[`performance_schema_max_sql_text_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_sql_text_length)服务器启动时的系统变量。更改会影响刚刚命名的所有列所需的存储空间。

    这[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)系统变量确定性能模式中摘要值存储的每个语句可用的最大字节数。但是，由于语句元素（如关键字和文字值）的内部编码，语句摘要的显示长度可能比可用缓冲区大小长。因此，从选择的值`DIGEST_TEXT`语句事件表的列可能看起来超过[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)价值。

    这[`events_statements_summary_by_digest`](performance-schema-statement-summary-tables.html)摘要表提供了服务器执行的语句的概要文件。它显示应用程序正在执行哪些类型的语句以及执行频率。应用程序开发人员可以将此信息与表中的其他信息一起使用来评估应用程序的性能特征。例如，显示等待时间、锁定时间或索引使用的表列可能会突出显示效率低下的查询类型。这使开发人员可以深入了解应用程序的哪些部分需要注意。

    这[`events_statements_summary_by_digest`](performance-schema-statement-summary-tables.html)汇总表具有固定大小。默认情况下，Performance Schema 会估计启动时使用的大小。要明确指定表大小，请设置[`performance_schema_digests_size`](performance-schema-system-variables.html#sysvar_performance_schema_digests_size)服务器启动时的系统变量。如果表已满，则性能模式将具有`SCHEMA_NAME`和`消化`值与特殊行中表中的现有值不匹配`SCHEMA_NAME`和`消化`调成`空值`.这允许计算所有语句。但是，如果特殊行占执行语句的很大比例，则可能需要通过增加[`performance_schema_digests_size`](performance-schema-system-variables.html#sysvar_performance_schema_digests_size).

### 语句摘要内存使用

对于生成仅在末尾不同的很长语句的应用程序，增加[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)启用摘要的计算，以区分否则将聚合到相同摘要的语句。反之，减少[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)导致服务器将更少的内存用于摘要存储，但增加了较长语句聚合到相同摘要的可能性。管理员应该记住，较大的值会导致相应增加的内存需求，特别是对于涉及大量同时会话的工作负载（服务器分配[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)每个会话的字节数）。

如前所述，由解析器计算的规范化语句摘要被限制为最大[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)字节，而存储在性能模式中的规范化语句摘要使用[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)字节。以下内存使用注意事项适用于相对值[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)和[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)：

-   如果[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)小于[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)：

    -   性能模式以外的服务器功能使用规范化的语句摘要，最多占用[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)字节。

    -   性能模式不会进一步截断它存储的规范化语句摘要，但分配的内存比[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)每个摘要的字节数，这是不必要的。

-   如果[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)等于[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)：

    -   性能模式以外的服务器功能使用规范化的语句摘要，最多占用[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)字节。

    -   性能模式不会进一步截断它存储的规范化语句摘要，并分配与[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)每个摘要的字节数。

-   如果[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)大于[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)：

    -   性能模式以外的服务器功能使用规范化的语句摘要，最多占用[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)字节。

    -   性能模式进一步截断它存储的规范化语句摘要，并分配比[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)每个摘要的字节数。

    因为 Performance Schema 语句事件表可能存储许多摘要，所以设置[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)小于[`最大摘要长度`](server-system-variables.html#sysvar_max_digest_length)使管理员能够平衡这些因素：

-   需要为性能模式之外的服务器功能提供长的规范化语句摘要

-   许多并发会话，每个会话分配摘要计算内存

-   存储许多语句摘要时需要限制性能模式语句事件表的内存消耗

    这[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)设置不是每个会话，是每个语句，一个会话可以存储多个语句[`events_statements_history`](performance-schema-events-statements-history-table.html)桌子。此表中的典型语句数是每个会话 10 个，因此每个会话消耗的内存是[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)值，仅针对此表。

    此外，在全球范围内收集了许多声明（和摘要），最值得注意的是[`events_statements_history_long`](performance-schema-events-statements-history-long-table.html)桌子。这里也，*`ñ`*存储的语句消耗*`ñ`*乘以所指示的内存[`performance_schema_max_digest_length`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_length)价值。

    要评估用于 SQL 语句存储和摘要计算的内存量，请使用[`显示引擎性能_架构状态`](show-engine.html)声明或监控这些工具：


```
mysql> SELECT NAME
       FROM performance_schema.setup_instruments
       WHERE NAME LIKE '%.sqltext';
+------------------------------------------------------------------+
| NAME                                                             |
+------------------------------------------------------------------+
| memory/performance_schema/events_statements_history.sqltext      |
| memory/performance_schema/events_statements_current.sqltext      |
| memory/performance_schema/events_statements_history_long.sqltext |
+------------------------------------------------------------------+

mysql> SELECT NAME
       FROM performance_schema.setup_instruments
       WHERE NAME LIKE 'memory/performance_schema/%.tokens';
+----------------------------------------------------------------------+
| NAME                                                                 |
+----------------------------------------------------------------------+
| memory/performance_schema/events_statements_history.tokens           |
| memory/performance_schema/events_statements_current.tokens           |
| memory/performance_schema/events_statements_summary_by_digest.tokens |
| memory/performance_schema/events_statements_history_long.tokens      |
+----------------------------------------------------------------------+
```

### 语句抽样

性能模式使用语句抽样来收集具有代表性的语句，这些语句在[`events_statements_summary_by_digest`](performance-schema-statement-summary-tables.html)桌子。这些列存储示例语句信息：`QUERY_SAMPLE_TEXT`（声明的文本），`QUERY_SAMPLE_SEEN`（当看到声明时），和`QUERY_SAMPLE_TIMER_WAIT`（语句等待或执行时间）。每次选择示例语句时，性能模式都会更新所有三列。

插入新表行时，生成行摘要值的语句将存储为与摘要关联的当前示例语句。此后，当服务器看到其他具有相同摘要值的语句时，它会决定是否使用新语句来替换当前的样本语句（即是否重新采样）。重采样策略基于当前示例语句和新语句的比较等待时间，以及可选的当前示例语句的年龄：

-   根据等待时间重采样：如果新语句等待时间的等待时间大于当前示例语句的等待时间，则成为当前示例语句。

-   基于年龄的重采样：如果[`performance_schema_max_digest_sample_age`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_sample_age)系统变量的值大于零，并且当前示例语句超过了几秒，当前语句被认为“太旧”并且新语句替换它。即使新语句等待时间小于当前示例语句的等待时间，也会发生这种情况。

    默认，[`performance_schema_max_digest_sample_age`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_sample_age)为 60 秒（1 分钟）。要更改样本语句因年龄而“过期”的速度，请增加或减少该值。要禁用重采样策略的基于年龄的部分，请设置[`performance_schema_max_digest_sample_age`](performance-schema-system-variables.html#sysvar_performance_schema_max_digest_sample_age)为 0。
