mysql数据库子查询的使用_MySQL数据库使用子查询方式更新数据优化及思考

【环境介绍】

云数据库MySQL 5.7

【背景描述】

业务需要:需要对16370077的表数据进行更新部分数据操作

UPDATE P_MOXXXX_REXXXX SET FISAVAILABLE = 1 WHERE FREG_ID IN (SELECT FREG_ID FROM P_MOXXXX_REXXXX_UPDATE_TEMP);

【按照正常流程更新数据操作】

使用archery的SQL审核工具进行提单操作,操作超过10分多钟,最后使用kill会话暂停操作,

SQL为子查询更新数据操作,业务反馈查询数据很快,从更新操作看执行很久时间:

26f05042f4e3f219452bf5814492554f.png

临时使用具体的条件值进行更新操作执行很快:

d5abcbedbfd4416ae2ed9703c2d1a3c3.png

【分析更新慢问题】

从查看SQL看为子查询更新数据操作,查看官方对子查询的解释:

701a4afa29cbe469e29141a7803f9c4d.png

官方解释数据库子查询很明确,更新,删除数据不能使用到半连接或者优化子查询方式优化,建议使用连接方式执行SQL。

semijoin实现策略

9be4e76b93110bfa73985680d478f91f.png

业务反馈查询数据很快,查看对应的执行计划信息,从执行计划中就可以马上看出问题,扫描数据跟驱动表很大的差别:

查询的执行计

13ad21e61d6485e6d9e80647f74274c7.png

从执行计划看,临时表作为驱动表,使用索引主键,从extra列看,使用了semijoin Duplicate Weedout 策略优化子查询;

ad8ecc74587f226580aee6e8fa7ae4be.png

update的执行计划:

11c83b15ea21b3885712d56d899ef07e.png

从执行计划看,不能优化成semijoin子查询,并且是一个相关子查询,会被优化器转为 exists相关子查询进行查询(select_type:DEPENDENT SUBQUERY),会根据外查询结果执行很多次;

【解决方法】

update/delete 无法使用 semijoin、materialization 优化策略,会以 exists 方式执行,外查询必须要进行全表扫描。

优化的方法,改成 join 即可方式更新数据操作;

4a01cca7e1351ecd5a65bb63ba498bb8.png

查看执行计划及更新操作:

daba7f749cb83bdb43b22a2e9ed0469c.png

从执行时间看执行了15.34秒

【参考资料】

https://dev.mysql.com/doc/refman/5.7/en/subquery-optimization.html

https://opensource.actionsky.com/20200628-mysql/

https://opensource.actionsky.com/20210202-explain/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值