暂无图片
暂无图片
2
暂无图片
暂无图片
1
暂无图片

MySQL 优化器提示(三)之 Optimizer Hints for Variable-Setting Hint Syntax

原创 aisql 2022-03-16
3962

MySQL8.0版本增加了 SET_VAR hint 可以指定变量只影响当前语句,对于调试生产环境非常有用,因为有可能在特定的语句我们希望更改一个变量值,因为是生产环境,又不想影响其它语句。比如一个排序语句特别慢。我们想加大sort_buffer_size 看看效果。下面就来慢慢聊聊一下。

一、定义

Syntax of the SET_VAR hint:
SET_VAR(var_name = value)

检查是否生效:

select @@max_length_for_sort_data
image.png

SELECT /*+ SET_VAR(max_length_for_sort_data = 2K) */ @@max_length_for_sort_data;
复制

image.png
通上图能看到。这个Variable-Setting Hint 生效了,在这个语句级别改为了2K

多个变量影响一个语句

SELECT /*+ SET_VAR(max_length_for_sort_data = 3M) SET_VAR(sort_buffer_size = 1G) SET_VAR(max_sort_length = 1M) */ @@max_length_for_sort_data,@@sort_buffer_size,@@max_sort_lengt
复制

image.png

通过上图可以看到三个变量都改了

影响范围

优化器影响范围有四种。Global、Query block、Table、index
这里贴上官方说明:
Optimizer Hint Overview
Optimizer hints apply at different scope levels:

Global: The hint affects the entire statement

Query block: The hint affects a particular query block within a statement

Table-level: The hint affects a particular table within a query block

Index-level: The hint affects a particular index within a table

而今天讲的 SET_VAR 就是 Global级的。

image.png

二、利用SET_VAR调优

顺便说一个MySQL排序

MySQL排序有两种:索引排索与文件排序
索引排索就是利用数据库中现有索引顺序输出,无需额外的排序。
文件排序是指无法利用索引排序,需要额外排序,当使用文件排序的时候,我们的执行计划中就会出现 Using filesort
文件排序又分为单路排序与双路排序,是全部在内存中完成的排序,还是在磁盘上排序了,然后归并排并这个执行计划并不知道。只有查optimizer_trace才能知道。

语句实例

先打开跟踪

set optimizer_trace = 'enabled=on'
复制

我先将max_length_for_sort_data改小。强制走双路排序

select /*+ SET_VAR(max_length_for_sort_data = 20) */ AGENTID,USERID,BEGINTIME from services where agentid = 'eeda9317cf4e44ac869f127be1b417b1' order by begintime desc limit 3000
复制

确认MySQL是否走的双路排序

select * from information_schema.optimizer_trace
复制

image.png

通过sort_mode可以确认上述语句就是采用的双路排序。

我们改大max_length_for_sort_data 试试

select /*+ SET_VAR(max_length_for_sort_data = 400) */ AGENTID,USERID,BEGINTIME from services where agentid = 'eeda9317cf4e44ac869f127be1b417b1' order by begintime desc limit 3000
复制
select * from information_schema.optimizer_trace
复制

image.png

可以看到的确走了单路排序了,因为单路排序把我查询的字段都放入了soft_buffer. 但sort_buffer_size太小,放不下。所以从num_initial_chunks_spilled_to_disk 看。产生了磁盘临时文件,不是在内存中完成的排序。

我们再继续调大 sort_buffer_size

select /*+ SET_VAR(max_length_for_sort_data = 400) SET_VAR(sort_buffer_size =1M ) */ AGENTID,USERID,BEGINTIME from services where agentid = 'eeda9317cf4e44ac869f127be1b417b1' order by begintime desc limit 3000
复制
select * from information_schema.optimizer_trace
复制

image.png

我们调大了sort_buffer_size 就可以看到直接走的内存排序了。

最后我们再关注一下。对于这个语句,当底 max_length_for_sort_data 与sort_buffer_size 设置多少合理呢。

上图中两个参数可以给我们答案:
max_length_for_sort_data : max_length_for_sort_data 只需要大于row_size 就会走单路排序。
sort_buffer_size: sort_buffer_size者 sort_buffer_size > peak_memory_used 就可以了。

如上图 row_size = 303 peak_memory_used = 911.4365KB。
我把这个语句设置为(max_length_for_sort_data = 304、sort_buffer_size =912k )

select /*+ SET_VAR(max_length_for_sort_data = 304) SET_VAR(sort_buffer_size =912k ) */ AGENTID,USERID,BEGINTIME from services where agentid = 'eeda9317cf4e44ac869f127be1b417b1' order by begintime desc limit 3000
复制
select * from information_schema.optimizer_trace
复制

image.png

可以看到。此语句还是采用的单路排序,且是在内存中完成的排序。

MySQL优化器提示系列文章

MySQL 优化器提示(一)之 Join-Order Optimizer Hints
MySQL 优化器提示(二)之 Optimizer Hints for Naming Query Blocks
MySQL 优化器提示(三)之 Optimizer Hints for Variable-Setting Hint Syntax

最后修改时间:2023-07-03 11:06:05
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

墨天轮福利君
暂无图片
3年前
评论
暂无图片 0
您好,您的文章已入选墨力原创作者计划合格奖,10墨值奖励已经到账请查收! ❤️我们还会实时派发您的流量收益。
3年前
暂无图片 点赞
评论