在mysql中翻页是不是有比LIMIT OFFSET更好的选择
阿神
阿神 2017-04-17 10:58:12
0
6
629

以前在数据中写翻页的代码时,一直把sql写成这样

SELECT * FROM table_name ORDER BY id ASC LIMIT 10 OFFSET 10

也就是用LIMITOFFSET来控制需要输出的内容区域,后来我在翻其他人代码时看到了这种写法

SELECT * FROM table_name WHERE id > 10 ORDER BY id ASC LIMIT 10

这种写法是否比前一种写法的速度要更快,因我看到它使用id主键的索引,而且还把检索区域用id > 10缩小了,理论上应该更快。但这种写法应该也有一定的局限性,比如最大的局限就是它只能用于那种类似timeline的,从第一页往后翻的应用场景,因为你要翻下一页必须知道前一页的最后偏移是多少。

不知道我这样的分析是否正确,各位有什么样的看法。

阿神
阿神

闭关修行中......

reply all(6)
PHPzhong

为了方便描述,下面id即指用来排序的字段

使用id > n 的方式,有局限性,但没有 @qinjianxiang 说的那么大。对于id不连续的问题,可以通过翻页的时候同时传入最后一个id方式来解决。比如:

//输出时,找出当前结果集中的最大最小id
//下一页
http://example.com/page.php?last=100
select * from table where id<100 order by id desc limit 10
//上一页
http://example.com/page.php?first=110
select * from table where id>110 order by id desc limit 10

这种方式比较大的缺点是,如果在浏览中有插入/删除操作,翻页不会更新,而总页数可能仍然是根据新的count(*) 来计算,最终可能会产生某些记录访问不到。为了修补这个问题,可以继续引入当前页码以及在上次翻页以后是否有插入/删除等影响总记录数的操作并进行缓存。

左手右手慢动作

MySQL里对LIMIT OFFSET的处理方式是,取出OFFSET+LIMIT的所有数据,然后去掉OFFSET,返回底部的LIMIT。
所以,在OFFSET数值较大时,MySQL的查询性能会非常低。

SELECT * FROM table_name ORDER BY id ASC LIMIT 10 OFFSET 10

MySQL会取出20条数据,只返回后10条。

SELECT * FROM table_name WHERE id > 10 ORDER BY id ASC LIMIT 10

利用id索引,MySQL只取出10个结果,返回。这种做法却是要求连续翻页,不能跳页,受约束。

洪涛

暂时没有更好选择,where id > :id的方式局限性太大,id不一定是连续的,翻页也不见得是根据主键来翻。

limit offset从功能上来讲是非常好的,如果担心offset过大时耗时太长,可以分库分表。或者用搜索引擎

黄舟

看到过一篇总结的比较全的文章:http://www.dewen.org/q/20/

PHPzhong

楼主的理解是对的。用id>m limit n 比用 limit m,n 快很多,主要原因是limit m,n需要去读取前面的m条记录。
如果是翻页需求,就在返回结果中取到最后的一个,再传给下一个链接。 @Rodin 给的方案就很好。

小葫芦

可以两种方式相结合,id>x limit m,n

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template