技术分享 | derived_condition_pushdown 影响外层 where 条件中用户自定义变量的使用

系统建
• 阅读 1738

作者:姚嵩

爱可生南区交付服务部经理,爱好音乐,动漫,电影,游戏,人文,美食,旅游,还有其他。虽然都很菜,但毕竟是爱好。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


摘抄: https://dev.mysql.com/doc/ref...

说明:

MySQL 8.0.22开始,新增了 optimizer_switch 参数,新增了 derived_condition_pushdown 变量,

启⽤用该变量后,可能会导致最外层 where 条件中使⽤了⽤户变量的 SQL 语句得到⾮预期的结果;

简单介绍:

derived_condition_pushdown 按字⾯意思就是派⽣条件下推;
MySQL8.0.22 开始对⽀持符合条件的子查询‘’进⾏派⽣条件下推,derived_condition_pushdown=ON 后,

对于查询:

SELECT * FROM (SELECT i, j FROM t1) AS dt WHERE i > constant

在许多情况下可能将外部的 where 条件下推到派⽣表,这会导致语句优化为:

SELECT * FROM (SELECT i, j FROM t1 WHERE i > constant) AS dt

这减少了派⽣表返回的⾏数,从⽽加快查询的速度。

测试语句:

select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;

变更 optimizer_switch 的语句(值可选OFF或ON):

set optimizer_switch='derived_condition_pushdown=on'; -- 设置当前会话

set global optimizer_switch='derived_condition_pushdown=on'; -- 设置全局值(影响后续新建的会话)

set persist optimizer_switch='derived_condition_pushdown=on'; -- 设置全局值,并固化到配置⽂件mysqld-auto.cnf;

测试 MySQL 版本:
MySQL8.0.23

当derived_condition_pushdown=ON时:

测试语句1:

set optimizer_switch='derived_condition_pushdown=on';
set @r=0;
select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;
explain select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;
set @r=1;
select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;
explain select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;

测试结果1:

技术分享 | derived_condition_pushdown 影响外层 where 条件中用户自定义变量的使用

测试语句2:

set @r=0;
select @r := 603014203924416,@i := 0 where @r<>0 ;
explain select @r := 603014203924416,@i := 0 where @r<>0 ;
set @r=1;
select @r := 603014203924416,@i := 0 where @r<>0 ;
explain select @r := 603014203924416,@i := 0 where @r<>0 ;

测试结果2:

技术分享 | derived_condition_pushdown 影响外层 where 条件中用户自定义变量的使用

测试结果说明:
当设置了 derived_condition_pushdown=ON 时: MySQL 执⾏了派⽣条件下推的优化,

将语句1

select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;

变更为语句2:

select @r := 603014203924416,@i := 0 where @r<>0 ;

⽽语句2中,是先筛选 where @r<>0 条件,然后再展示 @r := 603014203924416,@i := 0 的结果,

所以会利⽤ sesson 已有的@r的值进⾏ where 条件匹配,结果不符合预期。

当 derived_condition_pushdown=OFF 时:

测试语句1:

set optimizer_switch='derived_condition_pushdown=off';
set @r=0;
select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;
explain select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;
set @r=1;
select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;
explain select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;

测试结果1:

技术分享 | derived_condition_pushdown 影响外层 where 条件中用户自定义变量的使用

测试结果说明:

当设置了 derived_condition_pushdown=OFF 时:MySQL 执⾏语句1:

select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;

的步骤为:

  1. 先执⾏派⽣表: select @r := 603014203924416,@i := 0,此时@r为603014203924416 ;
  2. 再对结果集进⾏筛选 @r <> 0,得出结果,结果正确。

注意:

在 MySQL8.0.21 版本及之前版本,还没有参数 optimizer_switch,还没有derived_condition_pushdown变量,等价于 derived_condition_pushdown=off。

在 MySQL8.0.22 版本及之后版本,参数 optimizer_switch 引⼊了 derived_condition_pushdown 变量,在开启的时候,会导致下⾯的 SQL 语句及类似语句得到⾮预期的结果:

select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;

解决⽅法:

⽅法1:

set persist optimizer_switch='derived_condition_pushdown=off';

当然,也可以在执⾏ SQL 语句前,执⾏ session 级别的更改,只影响执⾏参数变更的 session :

set optimizer_switch='derived_condition_pushdown=on';

⽅法2:

改写 SQL ,让最外层的 where 条件不包含⽤户变量:

原语句:

select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;

改写后的语句:

select * from (select @r id,@i num from (select @r := 603014203924416,@i := 0) vars ) a where
id<>0 ;

⽅法3:

提前设置@r的值:

select @r := 603014203924416,@i := 0 ;
select * from (select @r := 603014203924416,@i := 0) vars where @r<>0 ;
点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
Java中Class对象详解
<divclass"htmledit\_views"id"content\_views"<phttps://blog.csdn.net/mcryeasy/article/details/52344729<br</p<p待优化整理总结</p<p</p<h1style"padding:0px;fontfamily:'apple
Stella981 Stella981
3年前
Exceptionless
<divid"cnblogs\_post\_body"class"blogpostbodycnblogsmarkdown"<h1id"exceptionless.netcore开源日志框架"Exceptionless.NetCore开源日志框架</h1<blockquote<p作者:markjiang7m2<b
Wesley13 Wesley13
3年前
P2P技术详解(三):P2P中的NAT穿越(打洞)方案详解(进阶分析篇)
1、引言接本系列的上一篇《P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解(基本原理篇)(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Flinks.jianshu.com%2Fgo%3Fto%3Dhttp%253A%252F%252Fwww.52im
Wesley13 Wesley13
3年前
P2P技术揭秘.P2P网络技术原理与典型系统开发
Modular.Java(2009.06)\.Craig.Walls.文字版.pdf:http://www.t00y.com/file/59501950(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.t00y.com%2Ffile%2F59501950)\More.E
Stella981 Stella981
3年前
Django之Django模板
1、问:html页面从数据库中读出DateTimeField字段时,显示的时间格式和数据库中存放的格式不一致,比如数据库字段内容为2012082616:00:00,但是页面显示的却是Aug.26,2012,4p.m.答:为了页面和数据库中显示一致,需要在页面格式化时间,需要添加<td{{dayrecord.p\_time|date:
Wesley13 Wesley13
3年前
Java 9版本之后Base64Encoder和Base64Decoder无法继续使用解决办法
<divclass"htmledit\_views"id"content\_views"<p在项目开发过程中,因为重装系统,安装了Java10版本,发现sun.misc.Base64Encoder和sun.misc.Base64Decoder无法使用。</p<p<br</p<p<strong原因:</strong</p<p查看
Wesley13 Wesley13
3年前
P1
通过本文,您的收获可能有:从课下部分,了解一些基本部件搭建时可能遇到的坑点,稍微深入一点理解两种状态机的区别;从课上测试部分,可以了解重点的考察内容,明白设计时状态机的类型在测试中的重要性。课下测试部分:课下测试主要考察了splitter的实现,ALU的实现,格雷码计数器的实现,扩位器的实现,以及合法表达式判别的有限状态机问题。本次课下部分比
Stella981 Stella981
3年前
Dubbo爆出严重漏洞!可导致网站被控制、数据泄露!附解决方案
http://dy.163.com/v2/article/detail/F5FPIFRU0511Q1AF.html  !(http://dingyue.ws.126.net/2020/0216/125ec4c4p00q5rcrs0019d200ig009qg00ig009q.png)  来源:华为云  原文地址:https://w
Wesley13 Wesley13
3年前
CDN+P2P在大规模直播&实时直播的技术实践
摘要:本次分享将介绍爱奇艺多类型的直播业务现状,以及直播整体技术架构和客户端直播网络模块Livenet的实现。回顾直播技术顺应业务多样化的演进过程,包括从偏P2P架构发展到结合CDN&P2P混合架构,为多端适配而实现的多协议支持和切换等演变,直播P2P和直播推流SDK的技术实现等。演讲/周志伟整理/LiveVideoStack
Stella981 Stella981
3年前
2018java面试集合
作者:刘成链接:https://www.zhihu.com/question/266822548/answer/317700943来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。另一个java后端面试总结:http://www.cnblogs.com/java1024/p/7685400.html39
可莉 可莉
3年前
2018java面试集合
作者:刘成链接:https://www.zhihu.com/question/266822548/answer/317700943来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。另一个java后端面试总结:http://www.cnblogs.com/java1024/p/7685400.html39