我们知道,limit分页,当翻到比较靠后的页时,查询效率会越来越慢。如这则帖子所述:
浅谈PageHelper插件分页实现原理及大数据量下SQL查询效率问题解决
博主这也是一种不错的思路。其实针对分页这个问题,了解其为什么慢就知道优化方法了,按我的理解如下(不一定说的很准确哈):
(1)以前
select * from table order by id limit 100, 10
这种方式,分页是怎么分的呢,是从磁盘拿整一个数据页到存储引擎缓冲区,比如 limit 100, 10 那就要按顺序先取出前100条数据,跳过了offset后再拿出第[100,110]这10条数据,如果这条数据字段很多且体积比较大,那么数据页就会比较大,我们知道存储引擎内存页大小是有限制的,如果数据页较大,那可能一次内存页只能存一两条数据,那么每次磁盘IO只能取到一两条,所以要翻掉前100条,那就可能需要非常多次的IO,这就是为什么慢的原因。
(2)针对上述问题,主要有两种优化思路,第一种就是针对“按顺序取前100条”这个问题,那我是不是可以不用取完前面100条就能拿到第[100,110]条呢?方法的话比如改造
limit 100,10
这个sql,用
where id > 100 limit 10
,这样的话可以按 id 主键索引先定位到哪个磁盘数据页,然后按顺序取10条数据就好了。
(2)第二种思路是针对“取大数据页到内存进行过滤”的问题,那我能不能把数据页做小,使得一个内存页能容纳更多条数据,从而减少磁盘IO次数?又或者我直接通过索引页来过滤,这样就不需要用原数据页来进行内存计算?这就是类似博主所述的方法,就是通过
select id from table limit 100,10
先分页查出id,再回表查询将这10个id的数据取出来就好了,因为id是主键索引,所以拿id来内存计算,就比拿一整页数据计算,IO次数要少的多了(甚至,存储引擎可能把id索引页都缓存到cache中了的话,压根都不需要硬盘IO了)。
版权归原作者 Victor _Lv 所有, 如有侵权,请联系我们删除。