代码之家  ›  专栏  ›  技术社区  ›  Evernoob

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

  •  7
  • Evernoob  · 技术社区  · 16 年前

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

    SELECT * FROM my_table LIMIT 10000, 20;
    

    这意味着MySQL仍将读取前10000条记录,并在生成我们想要的20条记录之前将其丢弃。

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

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

    干杯

    7 回复  |  直到 13 年前
        1
  •  7
  •   Josh Davis    16 年前

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

    SELECT * FROM my_table ORDER BY id LIMIT 20
    

    您将拥有前20条记录,假设它们的id是:5,8,9,…,55,64。到第2页的分页链接看起来像“list.php?page=2&id=64”,您的查询将是

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

    没有偏移,只读取20条记录。它不允许您任意跳转到任何页面,但大多数情况下人们只是浏览下一页/上一页。“id”上的索引将提高性能,即使偏移量很大。

        2
  •  1
  •   Community Mohan Dere    9 年前

    一个解决方案可能是不使用limit子句,而是使用join——在用作某种序列的表上进行连接。

    关于更多信息,我发现了这个 question / answer ,它给出了一个可能对您有所帮助的示例;-)

        3
  •  1
  •   Amber    16 年前

    基本上有3种方法,每种方法都有各自的优缺点:

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

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

        4
  •  1
  •   TeAmEr    15 年前
    SELECT * FROM my_table LIMIT 10000, 20;
    

    任何其他分页方法都会像使用连接方法一样承受巨大的负载

        5
  •  0
  •   Alix Axel    16 年前

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

        6
  •  0
  •   Vitaly Dyatlov    16 年前

    最好的方法是在my_表中定义索引字段,并为每个新插入的行增加该字段。毕竟,您需要使用介于10000和10020之间的索引字段

        7
  •  0
  •   MANCHUCK    16 年前

    其他一些选择,

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