29.10 性能模式语句摘要和采样
MySQL服务器能够维护语句摘要信息。摘要过程将每个SQL语句转换为标准化形式(即语句摘要)并从标准化结果中计算一个SHA-256哈希值(即摘要哈希值)。标准化允许将类似的语句进行分组和总结,以揭示服务器正在执行的语句类型及其频率。对于每个摘要,代表该摘要的语句作为样本被存储。这一节描述了如何在性能模式中实现语句摘要和采样,以及它们是如何有用的。
摘要过程在不考虑性能模式是否可用时由解析器执行,因此其他功能,如MySQL Enterprise Firewall和查询重写插件,可以访问语句摘要。
当解析器接收一个SQL语句时,它会计算一个语句摘要,如果需要的话,这通常是因为以下任何条件为真:
-
性能模式的摘要指令化已启用
-
MySQL Enterprise Firewall已启用
-
有查询重写插件已启用
解析器还用于STATEMENT_DIGEST_TEXT()
和STATEMENT_DIGEST()
函数,这些函数允许应用程序计算一个SQL语句的标准化摘要和一个摘要哈希值。应用程序可以调用这些函数来从SQL语句中计算标准化摘要和摘要哈希值。
max_ digest_length
系统变量的值确定每个会话可用于计算标准化语句摘要的最大字节数。一旦在摘要计算过程中使用了该数量的字节,截断发生:不会收集或考虑解析后的任何其他令牌。产生相同标准化语句摘要的语句,只要它们在那个数量的字节内不同,将被认为是相同的,如果进行比较或聚合以用于摘要统计。
将max_ digest_length
系统变量设置为零会禁用摘要生产,这也会禁用需要摘要的服务器功能。
在计算标准化语句后,会从中计算一个SHA-256哈希值。此外:
-
如果MySQL Enterprise Firewall已启用,它将被调用,并且可用于它的摘要。
-
如果有任何查询重写插件已启用,它们将被调用,语句摘要和摘要哈希值将被提供给它们。
-
如果性能模式的摘要指令化已启用,它会复制标准化的语句摘要,将其分配一个最大长度为
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 ...
在这种情况下,第二列名的差异丢失了,两个声明被认为是相同的。
在性能_schema中,语句摘要涉及这些元素:
-
一个
statements_digest
消费者在setup_consumers
表中控制性能_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
组合进行聚合。性能_schema使用SHA-256哈希值进行聚合,因为它们计算速度快,且有利于统计分布,减少了碰撞的可能性。请参阅第29.12.20.3节,“语句摘要表”。
一些性能表格有列用于存储原始SQL声明,这些声明用于计算摘要:
默认情况下,语句显示的最大空间为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
值的内存。
要评估用于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。