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