mysql 性能优化之exists 写法不一样,性能提升400倍

本文探讨了MySQL中使用EXISTS与IN子查询时的性能问题,特别是在不同版本间的表现差异,并提出了有效的优化策略。

业务需求 查询订单中包含商品《高性能 mysql》 的单据总量

上代码

select count(1) from saleorder a 
                          where a.tid = 180571   and exists(select 1 from saleorderdetail e1 where a.tid = e1.tid and a.billid = e1.billid and e1.goodsid in (1061)

执行时间为 16s

 

mysql 版本为 

5.6.16-log

查看执行计划

1PRIMARYarefPRIMARY,bo_billdate,bo_createdate,bo_billno,fk_saleorder_bid,fk_saleorder_cmpid,fk_saleorder_empid,fk_saleorder_storeid,fk_saleorder_useridbo_billdate4const13994Using where; Using index
2DEPENDENT SUBQUERYe1refPRIMARY,fk_saleorderdetail_skuid,fk_saleorderdetail_storeidfk_saleorderdetail_skuid8userdb0001.a.tid,const4

Using where; Using index

 

相同的语句 我再来看 8.0  中执行,只需要0.04S

mysql 版本为 

8.0.18

再 看执行计划 

SIMPLE<subquery2> ALL     100.00Using where
SIMPLEa eq_refPRIMARY,bo_billdate,bo_createdate,bo_billno,fk_saleorder_bid,fk_saleorder_cmpid,fk_saleorder_empid,fk_saleorder_storeid,fk_saleorder_useridPRIMARY12const,<subquery2>.billid1100.00Using index
MATERIALIZEDe1 refPRIMARY,fk_saleorderdetail_skuid,fk_saleorderdetail_storeidfk_saleorderdetail_skuid8const,const2402100.00Using index

 可以看到 8.0对子查询做了优化。

那么在 8.0以前版本中 exists怎么优化呢。

两种方案,1种是改写为 join

      select count(distinct a.tid,a.billid) from saleorder a  inner join saleorderdetail e1 on a.tid = e1.tid and a.billid = e1.billid
                                where a.tid = 180571  and  e1.goodsid in (1061) 

查询时间为0.04S

 

第二种方案,改in

select count(1) from saleorder a 
                                where a.tid = 180571  and (a.tid,a.billid) in (select tid,billid from  saleorderdetail e1 where e1.tid =180571 and  e1.goodsid in (1061))
     同样查询时间也只有 0.04S

 

 

结论 mysql 8.0以前的版本 要注意 exists与in 的子查询 会不会产生DEPENDENT SUBQUERY 如果产生,则必须优化它。

mysql 8.0及以后版本在子查询方面,做了较大优化。可以放心写。

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值