MySQL数据 - 实现分页的最佳方式?

ary*_*axt 182 mysql

我的iPhone应用程序连接到我的PHP Web服务以从MySQL数据库中检索数据.请求可以返回500个结果.

一次实现分页和检索20个项目的最佳方法是什么?

假设我收到了数据库中的前20个广告.现在我该如何申请接下来的20个广告?

Fai*_*roz 283

从MySQL文档:

LIMIT子句可用于约束SELECT语句返回的行数.LIMIT需要一个或两个数字参数,它们都必须是非负整数常量(使用预准备语句时除外).

使用两个参数,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数.初始行的偏移量为0(不是1):

SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15
Run Code Online (Sandbox Code Playgroud)

要从特定偏移量检索所有行直到结果集的末尾,可以使用一些大数字作为第二个参数.此语句检索从第96行到最后一行的所有行:

SELECT * FROM tbl LIMIT 95,18446744073709551615;
Run Code Online (Sandbox Code Playgroud)

使用一个参数,该值指定从结果集的开头返回的行数:

SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows
Run Code Online (Sandbox Code Playgroud)

换句话说,LIMIT row_count相当于LIMIT 0,row_count.

  • 使用LIMIT进行分页时,还应指定ORDER BY. (95认同)
  • @shylent:引用文档没有错,但我同意他应该提到他正在复制文档并提供了原始源的链接.另外,我很惊讶文档中会包含使用LIMIT而没有ORDER BY的例子......这似乎是一种鼓励的不良做法.如果没有ORDER BY,则无法保证调用之间的顺序相同. (9认同)
  • 无论如何,当对大型结果集进行分页时(这就是分页的用途 - 将大型结果集分解成更小的块,对吧?),你应该记住,如果你做一个"限制X,Y",那么基本上发生的是X +检索Y行,然后删除开头的X行,并返回任何左边的行.重申:"限制X,Y"导致扫描X + Y行. (9认同)
  • 我不喜欢你的LIMIT 95,18446744073709551615的想法..看看`OFFSET` ;-) (6认同)
  • 在处理大数据时这效率不高。检查http://codular.com/implementing-pagination,了解适合特定场景的多种方式。 (5认同)
  • 它来自 MySQL 文档。 (2认同)

Mar*_*ers 115

对于500条记录,效率可能不是问题,但如果您有数百万条记录,那么使用WHERE子句选择下一页是有利的:

SELECT *
FROM yourtable
WHERE id > 234374
ORDER BY id
LIMIT 20
Run Code Online (Sandbox Code Playgroud)

这里的"234374"是您查看的热门页面中最后一条记录的ID.

这将使id的索引能够用于查找第一条记录.如果你使用,LIMIT offset, 20你会发现它越来越慢,因为你的页面朝向最后.正如我所说,如果你只有200条记录可能无关紧要,但它可以对更大的结果集产生影响.

这种方法的另一个优点是,如果数据在呼叫之间发生变化,您将不会错过记录或获得重复记录.这是因为添加或删除行意味着更改后所有行的偏移量.在你的情况下,它可能并不重要 - 我猜你的广告池不会经常变化,无论如何没有人会注意到他们连续两次获得相同的广告 - 但如果你正在寻找"最好的方式"那么在选择使用哪种方法时要记住这一点.

如果您确实希望将LIMIT与偏移量一起使用(如果用户直接导航到页面10000而不是逐页遍历页面,则这是必要的)那么您可以阅读本文关于后期行查找以提高LIMIT的性能偏移.

  • 这样的分页只能向前发展 (8认同)
  • 但是人们多久想通过 ID 或通过暗示在现实世界中通过“创建日期”进行订购? (2认同)
  • 仅当您想按唯一属性(例如主键)排序时,这才有效。一旦你通过诸如日期之类的东西订购,这根本就不起作用。 (2认同)

小智 33

为查询定义OFFSET.例如

第1页 - (记录01-10):偏移= 0,极限= 10;

第2页 - (记录11-20)偏移= 10,极限= 10;

并使用以下查询:

SELECT column FROM table LIMIT {someLimit} OFFSET {someOffset};
Run Code Online (Sandbox Code Playgroud)

第2页的示例:

SELECT column FROM table
LIMIT 10 OFFSET 10;
Run Code Online (Sandbox Code Playgroud)


Luc*_*ein 21

有关于它的文献:

使用大OFFSETs 时会出现主要问题.它们避免使用OFFSET各种技术,从子句中的id范围选择WHERE到某种缓存或预计算页面.

使用INDEX,Luke建议的解决方案:


Bao*_* Le 12

本教程展示了一种很好的分页方式. 使用MySQL进行高效分页

简而言之,避免使用OFFSET或大LIMIT

  • 也许总结一下? (22认同)
  • 是的,我希望在回答中付出更多的努力。 (2认同)
  • 本质是:不要使用“OFFSET”,而是使用“ORDER BY”,并在用于排序的列上放置索引。现在我们可以使用“WHERE indexedColumn > lastSeenValue ORDER BY indexedColumn DESC LIMIT pageSize”进行过滤/分页。然后,对网络服务器的请求必须包含 lastSeen 值。 (2认同)

sur*_*ajz 5

你也可以

SELECT SQL_CALC_FOUND_ROWS * FROM tbl limit 0, 20
Run Code Online (Sandbox Code Playgroud)

select语句的行计数(没有限制)在同一个select语句中捕获,因此您无需再次查询表大小.您可以使用SELECT FOUND_ROWS()获取行计数;


小智 5

查询 1: SELECT * FROM yourtable WHERE id > 0 ORDER BY id LIMIT 500

查询 2: SELECT * FROM tbl LIMIT 0,500;

对于小型或中型记录,查询 1 运行得更快,如果记录数等于 5,000 或更多,则结果相似。

500 条记录的结果:

Query1 耗时 9.9999904632568 毫秒

Query2 耗时 19.999980926514 毫秒

8,000 条记录的结果:

Query1 耗时 129.99987602234 毫秒

Query2 需要 160.00008583069 毫秒

  • `id > 0` 有什么用? (8认同)