mysql 分页查询limit中偏移量offset过大导致性能问题

      在业务中经常会遇到关于分页的需求,这就会经常会用到MySQL中的limit offset,rows来分段取出每页中需要的数据。但是当数据量足够大的时候,limit条件中的偏移量offset越大就越会导致性能问题,导致查询耗时增加严重。先看一下测试:

-- 本地库中只有二百多万条数据,访者可以在本地将数据写入到千万条做测试。效果会更明显
select count(*) from notes;

                        

-- 发送不同级别偏移量的查询
set profiling=1;
select * from notes limit 100,3;
select * from notes limit 10000,3;
select * from notes limit 1000000,3;
select * from notes limit 10000000,3;

                      

-- 查看几条查询的耗时情况
show profiles

                     

-- 单独查看偏移量为一百万和一千万的查询
show profile for query 3;

   

        从人正常的逻辑去考虑limit 偏移量去取数据的话大家可能会考虑到从100开始取,取三条数据,那我就直接跳过前一百条数据,然后取出后面三条数据。但实际上MySQL并不是这么做的,查看上面两图中可以看到当偏移量增大时,Sending data是耗时的主要原因,这是因为MySQL并没有那么智能,并非是跳过偏移量取后面的数据而是先把偏移量+要取得条数,然后再把偏移量这一段的数据抛弃掉再返回。关于优化的解决方案的话大致可以分为几条:

       1> 在业务允许的情况下限制页数:

        可以看看百度和谷歌的做法,百度搜索出来的结果集的话最大的分页数是76页,可以想到76页已经是一个足够大的页数了,哪里会有人在那里一直翻页翻到76页,而谷歌更狠,我所查到的谷歌搜索结果集最大页数是28页,而且谷歌搜索出来的页数和百度不一样的是谷歌并非将页数定死的。

   

      2>  在大的数据量面前使用where id>offset 来代替使用limit offset:

-- 同样的效果
select * from notes limit 1000000,3;

select * from notes where id>1000000 limit 3;

        就像上图两条语句同样的效果但是第二条能提升不小的效率,但是这却会导致一个问题就是,如果选择这样去优化limit offset,其前提必须是主键id必须是连续的,可以在表内写入标记为做逻辑删除,不做物理删除。

    3>  假如说如果真的要物理删除,那解决方法的话就只能先取出前offset条数据的ID,再去做偏移取数据。

 

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值