【工作随手记】mysql优化之1
Published on 2022-10-31 10:33 in 暂未分类 with 是奉壹呀

【工作随手记】mysql优化之1

    原SQL:

    SELECT
    p.id,
    p.NAME,
    p.idcard,
    p.phone,
    p.plate,
    p.FAMILY_NO
    FROM
    t_person_info p
    WHERE
    p.id IN ( SELECT id FROM t_person_info WHERE FAMILY_NO = ( SELECT FAMILY_NO FROM t_person_info WHERE id = '1561155127086411776' ) )
    OR p.id = '1561155127086411776'

    执行计划:

    耗时:

    2.4秒

    优化思路:
    将人员的直接查出来,只有1条数据作为驱动表,再用户口号去关联原表。
    优化后的SQL:

    SELECT
    p.id,
    p.NAME,
    p.idcard,
    p.phone,
    p.plate,
    p.FAMILY_NO
    FROM
    t_person_info p
    right JOIN (select * from t_person_info where id = '1561155127086411776') p2 on p.FAMILY_NO = p2.FAMILY_NO

    执行计划

    耗时:

    0.03秒

    成功避免了两个子查询以及79万表的全表扫描。

    结论
    永远不要轻易使用【in子查询】,由于in子查询总是以外层查询的table作为驱动表,所以如果想用in子查询的话,一定要将外层查询的结果集降下来,降低io次数,降低nested loop循环次数,即:永远用小结果集驱动大的结果集。
    之前的SQL就是以大表t_person_info作为驱动表进行nested loop,该表数据越大,效率越慢。

    如sql

    SELECT
    p.id,
    p.NAME,
    p.idcard,
    p.phone,
    p.plate,
    p.FAMILY_NO
    FROM
    t_person_info p
    WHERE
    p.id IN ( SELECT id FROM t_person_info WHERE FAMILY_NO = '11697717')
    and p.id = '1561155127086411776'

    mysql优化器自动谓词下推,等价于:

    SELECT
    p.id,
    p.NAME,
    p.idcard,
    p.phone,
    p.plate,
    p.FAMILY_NO
    FROM
    (select * from t_person_info where id = '1561155127086411776') p
    WHERE
    p.id IN ( SELECT id FROM t_person_info WHERE FAMILY_NO = '11697717')

    这样驱动表结果集降到最低,效率也就提高了。这里只是举例,这条SQL并不符合业务场景。

    posted @   是奉壹呀  阅读(60)  评论(0编辑  收藏  举报
    相关博文:
    阅读排行:
    · 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
    · 单线程的Redis速度为什么快?
    · SQL Server 2025 AI相关能力初探
    · 展开说说关于C#中ORM框架的用法!
    · AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
    历史上的今天:
    2017-10-31 阿里巴巴Java开发手册与自己开发对照笔记
    点击右上角即可分享
    微信分享提示