如何使用PHP和MySQL有效地对大型数据集进行分页?

时间:2009-09-01 11:33:29

标签: php mysql pagination logic

正如你们中的一些人所知,在MySQL中使用LIMIT关键字并不妨碍它阅读前面的记录。

例如:

SELECT * FROM my_table LIMIT 10000, 20;

意味着MySQL仍然会读取前10,000条记录并在生成我们之后的20条记录之前抛弃它们。

因此,在对大型数据集进行分页时,高页码意味着加载时间过长。

有没有人知道任何现有的分页类/技术/方法能够以更有效的方式对大型数据集进行分页,即不依赖于LIMIT MySQL关键字?

如果可能的话,在PHP中,因为这是我公司的首选武器。

干杯。

7 个答案:

答案 0 :(得分:7)

首先,如果你想分页,你绝对必须有一个ORDER BY子句。然后,您只需使用该子句深入挖掘数据集。例如,考虑一下:

SELECT * FROM my_table ORDER BY id LIMIT 20

你将拥有前20条记录,让我们说它们的身份是:5,8,9,......,544。您对第2页的分页链接看起来像“list.php?page = 2& id = 64”,您的查询将是

SELECT * FROM my_table WHERE id > 64 ORDER BY id LIMIT 20

无偏移,只读取20条记录。它不允许您随意跳转到任何页面,但大多数时候人们只是浏览下一个/上一页。即使使用大量OFFSET值,“id”索引也会提高性能。

答案 1 :(得分:1)

解决方案可能是不使用limit子句,而是使用连接 - 连接用作某种序列的表。

对于更多信息,在SO上,我发现了这个question / answer,这给出了一个例子 - 可能对你有帮助; - )

答案 2 :(得分:1)

基本上有3种方法,每种方法都有自己的权衡:

  1. 将所有10000条记录发送到客户端,并通过Javascript等处理分页客户端。显而易见的好处是,所有记录只需要一个查询;明显的缺点是,如果记录大小有任何重要意义,发送到浏览器的页面大小将是相称的大小 - 用户可能实际上并不关心完整的记录集。

  2. 执行您当前正在执行的操作,即SQL LIMIT,并且只获取每个请求所需的记录,完全无状态。这样做的好处在于它只发送当前请求的页面的记录,因此请求很小,缺点在于a)它需要每个页面的服务器请求,以及b)随着后续页面的记录/页面数量的增加,它会变慢结果,如你所说。在单调递增的id字段上使用JOIN或WHERE子句有时可以在这方面提供帮助,特别是如果您从静态表请求结果而不是动态查询。

  3. 在服务器上维护某种状态对象,该状态对象缓存查询结果,并且可以在将来的请求中在有限的时间段内引用。好处是它具有最佳查询速度,因为实际查询只需要运行一次;缺点是必须管理/存储/清理这些状态对象(特别是对于高流量网站而言非常讨厌)。

答案 3 :(得分:1)

SELECT * FROM my_table LIMIT 10000, 20;

表示在搜索中显示从记录#10000开始的20条记录,如果你在where子句中使用主键,那么我的sql上不会有重负荷

任何其他pagnation方法都会像使用连接方法一样承担巨大的负担

答案 4 :(得分:0)

我不知道您提到的性能下降,我不知道任何其他分页解决方案,但ORDER BY子句可能会帮助您减少加载时间。

答案 5 :(得分:0)

最好的方法是在my_table中定义索引字段,并且对于每个新插入的行,您需要增加此字段。毕竟你需要使用WHOUR YOUR_INDEX_FIELD BETWEEN 10000和10020 它会快得多。

答案 6 :(得分:0)

其他一些选择,

  • 按每个页面对表格进行分区,因此忽略限制
  • 将结果存储到会话中(一个好主意是使用md5创建该数据的哈希,然后使用该缓存为每个多个用户创建会话)