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

MySQL 8.0.22 开始引入derived_condition_pushdown参数,该参数可能导致使用用户变量的SQL语句产生非预期结果。当derived_condition_pushdown=ON时,派生条件下推优化可能改变查询执行顺序,影响查询结果。文章通过实例展示了开启和关闭此参数时的不同行为,并提供了三种解决方法:关闭派生条件推下、改写SQL或提前设置用户变量的值。

作者:姚嵩

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

本文来源:原创投稿

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


摘抄: https://dev.mysql.com/doc/refman/8.0/en/derived-condition-pushdown-optimization.html

说明:

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:

测试语句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=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=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 ;
由于没有提供具体的参考引用内容,以下是基于一般知识对 `derived_upf` 的分析。 ### 含义 `derived_upf` 可能是“派生的用户平面功能(Derived User Plane Function)”的缩写。在通信网络尤其是 5G 网络架构中,用户平面功能(UPF)负责处理用户数据的转发和路由等功能。而“派生的”可能意味着它是基于某个基础 UPF 进行扩展、定制或者根据特定需求从原 UPF 衍生出来的功能实体。 ### 用途 - **特定业务适配**:可以针对特定的业务场景,如工业物联网、智能交通等,对基础 UPF 的功能进行调整和优化,以更好地满足这些业务对数据传输、处理的特殊要求。 - **网络切片定制**:在网络切片技术中,不同的切片可能需要不同的用户平面处理能力。`derived_upf` 可以为每个切片提供定制化的用户平面功能,确保切片之间的隔离性和独立性。 - **边缘计算集成**:在边缘计算场景下,`derived_upf` 可以部署在靠近用户设备的边缘节点,减少数据传输延迟,提高数据处理效率,实现对本地数据的快速处理和响应。 ### 相关技术信息 - **接口与协议**:`derived_upf` 可能需要遵循与基础 UPF 相同的接口和协议标准,如 N3 接口用于与无线接入网(RAN)通信,N4 接口用于与会话管理功能(SMF)通信等。同时,可能会根据其特定功能扩展一些新的接口和协议。 - **数据处理技术**:采用先进的数据转发和处理算法,如基于软件定义网络(SDN)和网络功能虚拟化(NFV)技术,实现灵活的流量调度和数据处理。 - **安全机制**:为了保障用户数据的安全和隐私,`derived_upf` 需要具备完善的安全机制,如加密、认证、访问控制等。 以下是一个简单的伪代码示例,模拟 `derived_upf` 对特定业务流量的处理: ```python class UPF: def __init__(self): self.routing_table = {} def forward_data(self, data, destination): if destination in self.routing_table: # 执行数据转发操作 print(f"Forwarding data to {destination}") else: print("Destination not found in routing table") class DerivedUPF(UPF): def __init__(self): super().__init__() # 扩展特定业务的处理逻辑 self.special_service_rules = {} def handle_special_service(self, data, service_type): if service_type in self.special_service_rules: # 执行特定业务的处理操作 print(f"Handling {service_type} service: {data}") else: print(f"No rule found for {service_type} service") # 创建 derived_upf 实例 derived_upf = DerivedUPF() # 模拟特定业务数据 special_data = "Special service data" service_type = "Industrial IoT" # 处理特定业务数据 derived_upf.handle_special_service(special_data, service_type) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值