首先看一下分页的基本原理:
复制代码 代码如下:
mysql> explain SELECT * FROM message ORDER BY id DESC LIMIT 10000, 20G ***************** 1. row ************** id: 1 select_type: SIMPLE table: message type: index possible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: 10020 Extra: 1 row in set (0.00 sec)
文中提到一种”clue”的做法,给翻页提供一些”线索”,比如还是SELECT * FROM message ORDER BY id DESC,按id降序分页,每页20条,当前是第10页,当前页条目id最大的是9527,最小的是9500,如果我们只提供”上一页”、”下一页”这样的跳转(不提供到第N页的跳转),那么在处理”上一页”的时候SQL语句可以是:
复制代码 代码如下:
SELECT * FROM message WHERE id > 9527 ORDER BY id ASC LIMIT 20;
处理”下一页”的时候SQL语句可以是:
复制代码 代码如下:
SELECT * FROM message WHERE id < 9500 ORDER BY id DESC LIMIT 20;
缺点是只能提供”上一页”、”下一页”的链接形式,但是我们的产品经理非常喜欢”<上一页 1 2 3 4 5 6 7 8 9 下一页>”这样的链接方式,怎么办呢?
如果LIMIT m,n不可避免的话,要优化效率,只有尽可能的让m小一下,我们扩展前面的”clue”做法,还是SELECT * FROM message ORDER BY id DESC,按id降序分页,每页20条,当前是第10页,当前页条目id最大的是9527,最小的是9500,比如要跳到第8页,我看的SQL语句可以这样写:
复制代码 代码如下:
SELECT * FROM message WHERE id > 9527 ORDER BY id ASC LIMIT 20,20;
复制代码 代码如下:
SELECT * FROM message WHERE id < 9500 ORDER BY id DESC LIMIT 40,20;
注意SQL语句里面的ASC和DESC,如果是ASC取出来的结果,显示的时候记得倒置一下。
已在60W数据总量的表中测试,效果非常明显。
新闻热点
疑难解答