MySQL 服务器能够维护语句摘要信息。摘要过程将每个 SQL 语句转换为规范化形式(语句摘要),并根据规范化结果计算 SHA-256 哈希值(摘要哈希值)。规范化允许对相似的语句进行分组和汇总,以公开有关服务器正在执行的语句类型及其出现频率的信息。对于每个摘要,生成该摘要的代表性语句将作为样本存储。本节介绍语句摘要和采样是如何发生的,以及它们如何发挥作用。
无论 Performance Schema 是否可用,摘要都在解析器中进行,以便其他功能(例如 MySQL 企业防火墙和查询重写插件)可以访问语句摘要。
当解析器接收到 SQL 语句时,如果需要该摘要,它将计算语句摘要,如果满足以下任何条件,则为 true:
启用了 Performance Schema 摘要检测
启用了 MySQL 企业防火墙
启用了查询重写插件
解析器也被 STATEMENT_DIGEST_TEXT()
和 STATEMENT_DIGEST()
函数使用,应用程序可以调用这些函数来分别从 SQL 语句计算规范化语句摘要和摘要哈希值。
max_digest_length
系统变量值决定了每个会话可用于计算规范化语句摘要的最大字节数。一旦在摘要计算期间使用了该空间量,就会发生截断:不会收集来自已解析语句的更多标记或将其计入其摘要值。如果比较或汇总以获取摘要统计信息,则仅在解析了这么多字节的标记后才不同的语句会产生相同的规范化语句摘要,并被视为相同。
将 max_digest_length
系统变量设置为零将禁用摘要生成,这也会禁用需要摘要的服务器功能。
计算规范化语句后,将根据它计算 SHA-256 哈希值。此外:
如果启用了 MySQL 企业防火墙,则会调用它,并且计算出的摘要可供其使用。
如果启用了任何查询重写插件,则会调用它,并且语句摘要和摘要值可供其使用。
如果 Performance Schema 启用了摘要检测,它将创建规范化语句摘要的副本,并为其分配最多
performance_schema_max_digest_length
个字节。因此,如果performance_schema_max_digest_length
小于max_digest_length
,则副本将相对于原始副本被截断。规范化语句摘要的副本与根据原始规范化语句计算出的 SHA-256 哈希值一起存储在相应的 Performance Schema 表中。(如果 Performance Schema 相对于原始语句截断了规范化语句摘要的副本,则它不会重新计算 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 = ?
如果规范化生成的语句超过了摘要缓冲区中的可用空间(由 max_digest_length
确定),则会发生截断,并且文本以 “...” 结尾。仅在 “...” 之后的不同部分的长的规范化语句被认为是相同的。考虑以下语句
SELECT * FROM mytable WHERE cola = 10 AND colb = 20
SELECT * FROM mytable WHERE cola = 10 AND colc = 20
如果截断恰好发生在 AND
之后,则两个语句都具有以下规范化形式
SELECT * FROM mytable WHERE cola = ? AND ...
在这种情况下,第二列名称的差异将丢失,并且两个语句被认为是相同的。
在性能模式中,语句摘要涉及以下元素
setup_consumers
表中的statements_digest
使用者控制性能模式是否维护摘要信息。请参阅语句摘要使用者。语句事件表(
events_statements_current
、events_statements_history
和events_statements_history_long
)具有用于存储规范化语句摘要和相应的摘要 SHA-256 哈希值的列DIGEST_TEXT
是规范化语句摘要的文本。这是原始规范化语句的副本,该语句被计算为最多max_digest_length
个字节,并根据需要进一步截断为performance_schema_max_digest_length
个字节。DIGEST
是根据原始规范化语句计算的摘要 SHA-256 哈希值。
events_statements_summary_by_digest
摘要表提供聚合的语句摘要信息。此表聚合每个SCHEMA_NAME
和DIGEST
组合的语句信息。性能模式使用 SHA-256 哈希值进行聚合,因为它们计算速度快,并且具有良好的统计分布,可以最大程度地减少冲突。请参阅第 29.12.20.3 节,“语句摘要表”。
一些性能表包含一列,用于存储从中计算摘要的原始 SQL 语句
events_statements_current
、events_statements_history
和events_statements_history_long
语句事件表的SQL_TEXT
列。events_statements_summary_by_digest
摘要表的QUERY_SAMPLE_TEXT
列。
默认情况下,语句显示的最大可用空间为 1024 字节。要更改此值,请在服务器启动时设置 performance_schema_max_sql_text_length
系统变量。更改会影响所有刚刚命名的列所需的存储空间。
performance_schema_max_digest_length
系统变量确定性能模式中每个语句可用于摘要值存储的最大字节数。但是,由于语句元素(例如关键字和文字值)的内部编码,语句摘要的显示长度可能比可用的缓冲区大小长。因此,从语句事件表的 DIGEST_TEXT
列中选择的值可能会超过 performance_schema_max_digest_length
值。
events_statements_summary_by_digest
摘要表提供了服务器执行的语句的配置文件。它显示了应用程序正在执行哪种语句以及执行频率。应用程序开发人员可以将此信息与表中的其他信息一起使用,以评估应用程序的性能特征。例如,显示等待时间、锁定时间或索引使用情况的表列可能会突出显示效率低下的查询类型。这使开发人员可以洞悉应用程序的哪些部分需要关注。
events_statements_summary_by_digest
摘要表的大小是固定的。默认情况下,性能模式会在启动时估算要使用的大小。要显式指定表大小,请在服务器启动时设置 performance_schema_digests_size
系统变量。如果表已满,则性能模式会将 SCHEMA_NAME
和 DIGEST
值与表中现有值不匹配的语句分组到一个特殊的行中,并将 SCHEMA_NAME
和 DIGEST
设置为 NULL
。这允许对所有语句进行计数。但是,如果特殊行占执行语句的很大一部分,则可能需要通过增加 performance_schema_digests_size
来增加摘要表的大小。
对于生成非常长的语句(仅在末尾不同)的应用程序,增加 max_digest_length
可以计算出区分语句的摘要,否则这些语句将聚合到同一个摘要中。相反,减少 max_digest_length
会导致服务器减少用于摘要存储的内存,但会增加较长语句聚合到同一个摘要中的可能性。管理员应记住,较大的值会导致相应的内存需求增加,特别是对于涉及大量并发会话的工作负载(服务器为每个会话分配 max_digest_length
个字节)。
如前所述,解析器计算的规范化语句摘要限制为最多 max_digest_length
个字节,而存储在性能模式中的规范化语句摘要使用 performance_schema_max_digest_length
个字节。以下内存使用注意事项适用于 max_digest_length
和 performance_schema_max_digest_length
的相对值
如果
max_digest_length
小于performance_schema_max_digest_length
性能模式以外的服务器功能使用最多占用
max_digest_length
个字节的规范化语句摘要。性能模式不会进一步截断它存储的规范化语句摘要,但会为每个摘要分配比
max_digest_length
个字节更多的内存,这是不必要的。
如果
max_digest_length
等于performance_schema_max_digest_length
性能模式以外的服务器功能使用最多占用
max_digest_length
个字节的规范化语句摘要。性能模式不会进一步截断它存储的规范化语句摘要,并且为每个摘要分配与
max_digest_length
个字节相同的内存量。
如果
max_digest_length
大于performance_schema_max_digest_length
性能模式以外的服务器功能使用最多占用
max_digest_length
个字节的规范化语句摘要。性能模式会进一步截断它存储的规范化语句摘要,并且为每个摘要分配的内存少于
max_digest_length
个字节。
因为性能模式语句事件表可能会存储许多摘要,所以将 performance_schema_max_digest_length
设置为小于 max_digest_length
可以使管理员能够平衡以下因素
需要为性能模式之外的服务器功能提供长的规范化语句摘要
许多并发会话,每个会话都分配摘要计算内存
需要在存储许多语句摘要时限制性能模式语句事件表的内存消耗
performance_schema_max_digest_length
设置不是针对每个会话的,而是针对每个语句的,并且一个会话可以在 events_statements_history
表中存储多个语句。此表中的典型语句数量为每个会话 10 个,因此仅此表,每个会话消耗的内存就为 performance_schema_max_digest_length
值指示的内存的 10 倍。
此外,还有许多全局收集的语句(和摘要),最显着的是 events_statements_history_long
表。同样,此处存储的 N
个语句消耗的内存为 performance_schema_max_digest_length
值指示的内存的 N
倍。
要评估用于 SQL 语句存储和摘要计算的内存量,请使用 SHOW ENGINE PERFORMANCE_SCHEMA STATUS
语句,或监视以下工具
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
表中生成每个摘要值。以下列存储示例语句信息:QUERY_SAMPLE_TEXT
(语句的文本)、QUERY_SAMPLE_SEEN
(看到语句的时间)和 QUERY_SAMPLE_TIMER_WAIT
(语句等待或执行时间)。每次选择示例语句时,性能模式都会更新所有三列。
插入新的表行时,生成行摘要值的语句将存储为与摘要关联的当前示例语句。此后,当服务器看到具有相同摘要值的其他语句时,它将确定是否使用新语句替换当前示例语句(即,是否重新采样)。重新采样策略基于当前示例语句和新语句的比较等待时间,以及(可选)当前示例语句的时效
基于等待时间的重采样:如果新语句的等待时间大于当前采样语句的等待时间,则新语句将成为当前采样语句。
基于时间的重采样:如果
performance_schema_max_digest_sample_age
系统变量的值大于零,并且当前采样语句的时长超过该值所定义的秒数,则当前语句将被视为“过时”,并由新语句替换。即使新语句的等待时间小于当前采样语句的等待时间,也会发生这种情况。
默认情况下,performance_schema_max_digest_sample_age
为 60 秒(1 分钟)。要更改采样语句因时间“过期”的速度,请增加或减少该值。要禁用重采样策略中基于时间的机制,请将 performance_schema_max_digest_sample_age
设置为 0。