这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战
📖摘要
鼓励有时比压力要重要!
在学习的过程中,很多时候我们听到的都是,你要怎样,怎样,你瞧瞧谁谁谁,哪怕今天听不到这样的声音了,但因为曾经反复听到过而导致内心抗拒。虽然也知道自己要去学,但是很难坚持,学着学着就没有了方向,看到还有那么多不会的就更慌了,以至于最后心态崩了,更不愿意学。其实程序员的压力并不小,想成长几乎是需要一直的学习,就像似乎再也不敢说精通java了一样,知识量实在是随着学习的深入,越来越深,越来越广。所以需要,开心学习,快乐成长!
🌂分享
在写一个分页查询记录的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 是循环主表的记录去关联另一张表,那么输出的顺序应该还是主表的顺序啊,但结果却是按另一张表的字段排序的,这又是为什么呢?
去官方手册中找找线索,发现 order by 模块中有这么一句话。
再去 limit 模块中看一下
从以上两个截图中,我们可以发现一些端倪,limit 操作会对查询有一些优化,查询到指定条数的数据,就可以提前结束了,比如我们本文中的 left 操作,拿到10条结果就结束查询线程,返回客户端。
猜测,如果没有 limit 操作,反正全部都要 join ,可能 mysql 会对循环逻辑做一些优化,不一定要按主表来循环,思想类似于 java 编译中的重排序,也对应了上面截图中的那句话。
采用最简单、最粗暴的方式,直接把 order by 和 limit 操作放到最外面就ok啦,其实效率上并没有什么降低,只要索引建的合理即可。
🎉最后
- 更多参考精彩博文请看这里:《陈永佳的博客》
- 喜欢博主的小伙伴可以加个关注、点个赞哦,持续更新嘿嘿!