高效的MySQL分页

网上有各种各样的MySQL分页,但是内容总是有些差错。经过查阅资料和自己的理解。关于MySQL高效分页内容整理如下:

MySQL数据库实现分页比较简单,提供了limit函数。一般只需要写到sql语句后面就行了。

//如果只给定一个参数,它表示返回最大的记录行数目: 
mysql> SELECT * FROM table LIMIT 5;     //检索前 5 个记录行
//换句话说,LIMIT n 等价于 LIMIT 0,n。

mysql> SELECT * FROM table LIMIT 5,10;  // 检索记录行 6-15
//为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1: 
mysql> SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.

 

首先看一下分页的基本原理:

mysql> explain SELECT * FROM message ORDER BY id DESC LIMIT 10000, 20\G  

***************** 1. row **************  

id: 1  

select_type: SIMPLE  

table: message  

type: index 

possible_keys: NULL 

keyPRIMARY 

key_len: 4  

10 ref: NULL 

11 rows: 10020  

12 Extra:  

13 1 row in set (0.00 sec) 

limit 10000,20的意思扫描满足条件的10020行,扔掉前面的10000行,返回最后的20行,问题就在这里,如果是limit 100000,100,需要扫描100100行,在一个高并发的应用里,每次查询需要扫描超过10W行,性能肯定大打折扣。文中还提到limit n性能是没问题的,因为只扫描n行。

文中提到一种”clue”的做法,给翻页提供一些”线索”,比如还是SELECT * FROM message ORDER BY id DESC,按id降序分页,每页2000条,当前是第50页,当前页条目id最大的是102000,最小的是100000(10w),如果我们只提供”上一页”、”下一页”这样的跳转(不提供到第N页的跳转),那么在处理”上一页”的时候SQL语句可以是:

14 SELECT * FROM message WHERE id < 100000 ORDER BY id DESC LIMIT 2000; 

处理”下一页”的时候SQL语句可以是:

15 SELECT * FROM message WHERE id > 102000 ORDER BY id ASC LIMIT 2000; 

不管翻多少页,每次查询只扫描2000行。

缺点是只能提供”上一页”、”下一页”的链接形式,但是我们的产品经理非常喜欢”<上一页 1 2 3 4 5 6 7 8 9 下一页>”这样的链接方式,怎么办呢?

如果LIMIT m,n不可避免的话,要优化效率,只有尽可能的让m小一下,我们扩展前面的”clue”做法,还是SELECT * FROM message ORDER BY id DESC,按id降序分页,每页2000条,当前是第50页,当前页条目id最大的是102000,最小的是102000,比如要跳到第51页,我看的SQL语句可以这样写:

16 SELECT * FROM message WHERE id > 102000 ORDER BY id ASC LIMIT 2000,2000; 

跳转到第48页:

17 SELECT * FROM message WHERE id < 100000 ORDER BY id DESC LIMIT 2000,4000; 

原理还是一样,记录住当前页id的最大值和最小值,计算跳转页面和当前页相对偏移,由于页面相近,这个偏移量不会很大,这样的话m值相对较小,大大减少扫描的行数。其实传统的limit m,n,相对的偏移一直是第一页,这样的话越翻到后面,效率越差,而上面给出的方法就没有这样的问题。

注意SQL语句里面的ASC和DESC,如果是ASC取出来的结果,显示的时候记得倒置一下。

已在60W数据总量的表中测试,效果非常明显。


 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值