mysql in 加子查询,mysql in子查询的优化

项目遇到一个MySQL查询特别慢的语句:

SELECT *

FROM (

SELECT DISTINCT t.vc_date, t.c_bankno, t.vc_bankacco, t.vc_moneytype, t.en_totalbala

FROM tbankaccobala t

WHERE 1 = 1

AND t.id IN (

-- 这个查询需要3s:

SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1)

FROM tbankaccobala

GROUP BY vc_bankacco

)

) t

这个语句导致前端页面10秒左右才有响应(但MySQL执行显示要4.6秒,phpMyAdmin也是10秒左右响应,为何?)

但如果把IN语句里面的内容改成下面这样,只在外层再加一个select,就只要0.006s:

SELECT hhhh from(

SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1) as hhhh

FROM tbankaccobala

GROUP BY vc_bankacco

) as sbstr

-- 对IN的子查询做二次select,或者把IN改为JOIN都可以解决速度奇慢的问题

原语句空行处省略了一系列的其他表和 INNER JOIN 语句。一开始怀疑是多表的JOIN操作导致速度变慢,但删去JOIN变成上面这段注释掉的语句之后,速度依然非常慢,显示要3s,于是猜测 IN 才是导致速度变慢的主要因素,改后只要0.006s,啧…

EXPLAIN 未优化的语句:

20190820091535632629.png

(相关子查询是使用外部查询中的值的子查询)

EXPLAIN 优化的语句:

20190820091535757633.png

我的理解:优化前,子查询是相关子查询,对于外部产生的每个值,都要执行一次子查询;优化后,子查询不再是相关子查询,只需要执行一次子查询并缓存中间结果,外部查到的每个值去缓存的中间结果里比对一下就行了。

(有人说是能不能用索引的原因——这么说应该是不对的)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值