Mysql group by后加 limit 查询很慢的坑

时间:2024-04-06 22:11:22

前言

最近踩了一个大坑,虽然快速解决了,但是当时也没有想明白为什么。起因是在改造一条sql语句时候,需要加group by,我当时就没有多想,直接就加上了,确认了sql可以正常查询之后,我就开始运行项目测试了。用的是baomidou的mybitis插件,这个查询最终是会通过mybatis的处理加上limit的,然后让我震惊的现象出现了,这条我在数据库操作工具测试过的sql,在加上了limit之后,接口迟迟不返回结果,最终报错,观察日志发现,sql执行了70多秒,导致接口超时,被springcloud熔断掉了,我马上复制了完整的sql在数据库操作工具里测试,和程序的情况一样,在加上了分页参数limit之后,整整查了60s,这是不能接受的,为了赶快解决问题,后来查了资料,在sql外包裹了一层查询后解决掉了。

解决思路

  1. 确定是否真的是gourp by 与 limit组合使用的影响。我分别观察了group by和limit分别使用以及一起使用的查询速度,结果是肯定的,group by和limit一起使用确实有问题。

  2. 分析sql执行计划

    Mysql group by后加 limit 查询很慢的坑
    Mysql group by后加 limit 查询很慢的坑
    分析:
    在一个全表扫描19000条数据的操作上,同时出现了Using temporary和Using filesort,这肯定会造成sql查询缓慢
    在一个全表扫描7000条数据的操作上,出现了Using where; Using join buffer (Block Nested Loop),mysql在5.5版本中引入了BNL的算法,可以有效地减少多表关联查询对内部表扫描数量。
    虽然到此,已经确定了问题的本质,但是还没有想到解决办法,初步猜想是因为limit的操作涉及到主键ui.id,并且ui.id进行分组,导致索引失效
    继续搜索资料。
    巧的是,找到了一篇和我一样问题的文章,同样是group by和limit连用造成的sql执行缓慢,给出的解决方法是在sql外层嵌套一层查询,把现有sql当作子查询,间接分开了group by与limit的连用,让limit根据子查询结果集来操作。

总结

待续~