sql相关子查询的一个小知识点

2 篇文章 0 订阅

最近遇到一个耗时很长的sql,如下

    SELECT u.login_name , u.name name ,CONCAT( u.idcard,'') idcard
        ,u.phone
        phone,s.code code,c.name classroomName,d.name deptName ,
        (SELECT d.name FROM dept d WHERE d.id = getDeptHospitalId(u.dept_id) )
        hospitalName,p.name paperName,examset.name examsetName,exam.name
        examName
        ,e.mark/100 mark ,exam.start_dt examTime,
        (CASE e.state WHEN
        'A' THEN '是'
        ELSE '否' END) state
        FROM examinee e
        LEFT JOIN USER u ON u.id
        = e.user_id
        LEFT JOIN dept d ON d.id = u.dept_id
        LEFT JOIN plan p ON
        p.id = e.plan_id
        LEFT JOIN seat s ON s.id = e.seat_id
        LEFT JOIN
        classroom c ON c.id = s.classroom_id
        LEFT JOIN exam on exam.id =
        e.exam_id
        LEFT JOIN examset on examset.id = exam.examset_id
        WHERE
        exam_id =  '7bee06c7-8e0d-4af0-86eb-efed0edd2075'
该sql用时约10s,这还只是数据量少的时候,数据量庞大起来甚至是以分钟计时。

一开始我以为是因为索引没有添加,但是查看后发现连接字段都有索引,继续分析,我explain这句sql出来一看,终于找到问题
这里写图片描述

问题出在这里...(SELECT d.name FROM dept d WHERE d.id = getDeptHospitalId(u.dept_id) ) hospitalName,

这里这句相关子查询依赖于外部查询,也就是外部查询执行一行,子查询就执行一次。假如只是如此也没啥问题,添加索引仍能使它变快,但是在这里连接部分使用了自定义函数,这就导致了mysql将不会使用索引而全表查询。导致查询异常的缓慢。甚至拆成两个独立查询顺序执行更为快捷。

我的解决方式:临时表联表查询

SELECT a.*,dept.`name` hospitalName from (SELECT u.login_name , u.name name ,CONCAT( u.idcard,'') idcard
        ,u.phone phone,getDeptHospitalId(u.dept_id) d_id,
        s.code code,c.name classroomName,d.name deptName,p.name paperName,examset.name examsetName,exam.name
        examName
        ,e.mark/100 mark ,exam.start_dt examTime,
        (CASE e.state WHEN
        'A' THEN '是'
        ELSE '否' END) state
        FROM examinee e 
        LEFT JOIN USER u ON u.id
        = e.user_id
        LEFT JOIN dept d ON d.id = u.dept_id
        LEFT JOIN plan p ON
        p.id = e.plan_id
        LEFT JOIN seat s ON s.id = e.seat_id
        LEFT JOIN
        classroom c ON c.id = s.classroom_id
        LEFT JOIN exam on exam.id =
        e.exam_id
        LEFT JOIN examset on examset.id = exam.examset_id
        WHERE
        exam_id =  '7bee06c7-8e0d-4af0-86eb-efed0edd2075'
) a LEFT JOIN dept on dept.id=a.d_id

查询时间降至10ms左右
参考资料:[慢查优化]慎用MySQL子查询,尤其是看到DEPENDENT SUBQUERY标记时

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值