今天写出一个十分弱智的bug!

今天写出一个十分弱智的bug!_第1张图片

今天写出一个十分弱智的bug,记录一下,提醒自己以后别这种犯错,不怕丢人哈~

在写一个分页查询记录的sql时,要根据添加的时间逆序分页输出,之前的写法是酱紫:

select
    record.a,
    y.c
from
    (
        select
            a,b
        from
            x
        order by timestamp desc
        limit 0,10
    ) record
left join y
on record.b = y.d;

因为一些新的需求,要在后面加一些where条件,limit操作不能在嵌套查询里面加了,于是乎把limit 0,10提出来放到最外面,结果order by还留在里面。

我当时想嵌套查询出来的record表已经按timestamp字段逆序排列了,再left另一张表,最终再limit出来的结果应该也是逆序的,但结果却很打脸,是正序的。

首先控制变量,代码回滚到之前,把后来加的各种逻辑都去掉,还原到上述sql,只把limit 0,10移到最后,发现timestamp是正序的,那么问题应该就出在这里了,与后来加的其他逻辑没有关系。

那么再试一下删掉limit操作,结果timestamp是无序的!

这不可能啊,于是认真看了下数据,发现一些规律,可能是按y表的自增id或created_at时间字段排序的(因为这两个字段是索引字段),那么到这里,我们至少可以得到一个简单的结论,就是联表查询结果,不是按照嵌套查询中的order by排序的,现在正向一看,确实不可能按这个排序,因为括号里面的逻辑对括号外是不可见的。

还有个问题,上述去掉limit后,最终不是按left join主表的顺序输出,按照我们常理想象,mysql是循环主表的记录去关联另一张表,那么输出的顺序应该还是主表的顺序啊,但结果却是按另一张表的字段排序的,这又是为什么呢?图解 5 种 Join 连接这篇推荐大家看下。


去官方手册中找找线索,发现order by模块中有这么一句话。

再去limit模块中看一下

今天写出一个十分弱智的bug!_第2张图片

从以上两个截图中,我们可以发现一些端倪,limit操作会对查询有一些优化,查询到指定条数的数据,就可以提前结束了,比如我们本文中的left操作,拿到10条结果就结束查询线程,返回客户端。

我猜测,如果没有limit操作,反正全部都要join,可能mysql会对循环逻辑做一些优化,不一定要按主表来循环,思想类似于java编译中的重排序,也对应了上面截图中的那句话。

采用最简单、最粗暴的方式,直接把order by 和 limit操作放到最外面就ok啦,其实效率上并没有什么降低,只要索引建的合理即可。

作者:春卷要炸着吃

www.cnblogs.com/supercj/p/10333918.html

END

学习资料:

分享一份最新 Java 架构师学习资料

最近热文:

1、Tomcat 爆出高危漏洞!

2、基于 Gitlab 的代码审查,简单实用

3、阿里面试 Java 都问什么?万字总结!

4、为啥老外偏爱 Hibernate/JPA 呢?

5、程序员接私活,怎样防止做完不给钱?

6、Git 高级用法,喜欢就拿去用!

7、7 种 JVM 垃圾收集器,看完我跪了。

8、Spring 解决循环依赖的 3 种方式!

9、推荐一款 Vim 神器,666!

10、Redis牛逼!轻松实现实时订阅推送

短视频:

1、Java 24 年发展史,辉煌的 24 年!

2、什么是悲观锁和乐观锁?

3、Java 8 中的永久代去哪了?

4、switch case 支持哪几种数据类型?

5、一图搞懂 Java 中的异常分类!

公众号干货实在太多了,扫码关注Java技术栈公众号看更多。

点击「阅读原文」带你飞~

你可能感兴趣的:(今天写出一个十分弱智的bug!)