引言
现在越来越多的项目使用代码生成器,所以我们写分页的时候基本都是直接用代码生成器生成的代码,就算是需要关联多表自定义SQL查询分页,也是用left join
进行关联,那么,各位有没有想过这么一个问题,当生产环境的表到达百万获千万以上数据时,进行分页查询,用left join
分最后几页的时候(甚至都不到一半都慢了许多。。)还合适吗?
正文
left join(常规的limit)
适用于记录数少的表,例如类型表等;
其实在表数据不大的时候,适用left join
关联表无伤大雅,就算是分页也体现不出效率上的差距,就算是直接在分最后一页时你也感受不到差别。
延迟关联与子查询
适用于记录数突破百万以上等大数据量的表,例如订单等;
注意:MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回
N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过
特定阈值的页数进行 SQL 改写。
SQL_CALC_FOUND_ROWS
到目前都还是有对SQL_CALC_FOUND_ROWS
与count(*)
哪个效率更高还是表示怀疑,网上的说法也不尽相同,SQL_CALC_FOUND_ROWS
适合where字句异常复杂耗时的情况。在频繁使用查询的应用中,这个方法能够带来1/3的数据库性能提升。
分页选择优先级
数据量不大的时候:使用哪一种都不具备明显差距;
数据量大的时候(这里我要声明一下,我做出的排名是根据自己试验与阿里巴巴推荐综合考虑出的选择):
延迟关联与子查询 > SQL_CALC_FOUND_ROWS > left join(即常规的limit)
小技巧
1,在分页前,应该先查询分页的count
,如果是0,就说明没有数据,直接返回就可以了;
2,对你的分页SQL进行explain
,如果extra出现:using index,说明使用的是覆盖索引,覆盖索引是一种查询的一种
效果,可以避免回表操作。
结语
有疑问的朋友可以自行去百度这三种分页选择的详细说明,阿里巴巴开发手册推荐的是延迟关联与子查询做大数据量的分页查询,而SQL_CALC_FOUND_ROWS确实是要比常规的left join(常规分页)要快的。