请不要将OFFSET和LIMIT用于分页

不再需要担心数据库性能优化的日子已经一去不复返了。

随着时代的发展,每个新企业家都希望建立下一个Facebook,并结合收集每个可能的数据点以提供更好的机器学习预测的心态,作为开发人员,我们需要比以往更好地准备我们的API,以提供可靠,高效的端点,应该能够毫不费力地浏览大量数据。

如果您已经进行了一段时间的后端或数据库体系结构,则可能已经完成了分页查询,如下所示:

对?

但是,如果您确实建立了这样的分页,很遗憾地说,您做错了。

你不同意我吗? 并不 需要 Slack, ShopifyMixmax使用我们今天将要讨论的相同概念对API进行分页。

我想请您说说一个单一的后端开发人员,该人员从来没有为了分页目的而需要处理OFFSET和LIMIT。 对于MVP和低数据列表中的分页,它“有效”。

但是,当您想从头开始构建可靠而有效的系统时,也可以直接进行。

今天,我们将讨论(错误地)广泛使用的实现所存在的问题以及如何实现高效的分页。

OFFSET和LIMIT有什么问题?

正如我们在上几段中简要探讨的那样,OFFSET和LIMIT非常适合于数据使用量很少甚至没有的项目。

当数据库开始收集的数据量超出服务器可以存储在内存中的数据量时,仍然会出现问题,而您仍然需要对它们全部进行性能分页。

为此,每次您请求分页时,数据库都需要执行低效的全表扫描 (插入和删除可能同时发生,我们不希望数据过时!)。

什么是全表扫描? 全表扫描(又称顺序扫描)是在数据库中进行的扫描,其中顺序读取表中的每一行,然后检查遇到的列是否符合条件。 由于从磁盘进行大量的I / O读取(包括多次搜寻)以及昂贵的磁盘到内存传输,这种类型的扫描被认为是最慢的。

这意味着,如果您有100.000.000用户,而您要求的偏移量为50.000.000,则它将需要获取所有这些记录(甚至不需要!),并将它们存储在内存中,只有在获得之后, LIMIT中指定了20个结果。

因此,要在网站上显示这样的分页:

50.000至50.020之100.000

它首先需要获取50.000行。 看看这效率低下吗?

如果您不相信我,请看一下我创建的这个小提琴 。 在左侧面板中,您有一个基本架构,该架构将为我们的测试插入100.000行,而在右侧,则是有问题的查询和我们的解决方案。 只需单击顶部的“运行 ”,然后比较每个执行时间。 #1(问题查询)至少需要30秒钟的时间才能运行。

随着更多的数据,情况变得更加糟糕。 看看我的1000万行概念证明

现在,这应该使您对幕后发生的事情有所了解。 如果您喜欢阅读的内容,请在此处订阅以获取更多类似内容。

TLDR; 偏移量越高,查询将花费的时间越长。

您应该使用什么

这是您应该使用的:

这是基于游标的分页

您应该存储最后接收到的主键(通常是一个ID)和LIMIT,而不是在本地存储当前的OFFSET和LIMIT并随每个请求传递它,因此查询最终可能与此类似。

为什么? 因为通过显式传递最新的读取行,您可以根据有效的索引键告诉数据库确切从哪里开始搜索,而不必考虑该范围之外的任何行。

以下面的比较为例:

针对我们的优化版本:

接收到的记录完全相同,但是第一个查询花费了12.80秒,第二个查询花费了0.01秒。 你能体会到差异吗?

注意事项

为了使Cursor Pagination无缝地工作,您将需要具有一个唯一的顺序列(或多个列),例如唯一的整数ID或时间戳记字段,在某些特定情况下,这可能会破坏交易。

与往常一样,我的建议是始终考虑每种表体系结构的优缺点以及在每种表体系结构中需要执行哪种查询。

如果您需要在查询中处理大量相关数据,Rick James的“ 列表”文章可能会为您提供更深入的指导。 如果我们遇到的问题与没有主键有关,例如,如果我们有多对多关系表,则在这些情况下始终可以使用传统的OFFSET / LIMIT方法,但这将重新引入潜在的较慢查询。 因此,我建议在要分页的表中使用自动递增的主键,即使只是出于分页的目的。

结论

这样做的主要要点是始终检查查询的性能是1k行还是1M。 可伸缩性至关重要,如果从一开始就正确实施,肯定会避免将来出现很多麻烦。

哦。 并且,请不要忘记学习索引 。 并解释查询

如果您喜欢这篇文章,请 在此处订阅 以获取更多类似内容。

先前发布在 https://ivopereira.net/content/efficiency-pagination-dont-use-offset-limit

翻译自: https://hackernoon.com/please-dont-use-offset-and-limit-for-your-pagination-8ux3u4y

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,你可以使用SQL语句的`LIMIT`和`OFFSET`子句来进行数据查询的分页操作。`LIMIT`用于限制返回的结果数量,`OFFSET`用于指定从哪一行开始返回结果。 下面是一个示例代码,演示了如何在Java中使用`LIMIT`和`OFFSET`进行数据查询分页: ```java import java.sql.*; public class PaginationExample { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydatabase"; String username = "root"; String password = "password"; int pageSize = 10; // 每页显示的数据条数 int currentPage = 3; // 当前页码 try (Connection connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement()) { // 计算偏移量 int offset = (currentPage - 1) * pageSize; // 执行查询语句,使用LIMITOFFSET进行分页 String query = "SELECT * FROM mytable LIMIT " + pageSize + " OFFSET " + offset; ResultSet resultSet = statement.executeQuery(query); // 遍历结果集 while (resultSet.next()) { // 处理每条记录 int id = resultSet.getInt("id"); String name = resultSet.getString("name"); // ... 其他字段 System.out.println("ID: " + id + ", Name: " + name); } } catch (SQLException e) { e.printStackTrace(); } } } ``` 在上面的示例中,我们假设使用MySQL数据库,并且已经建立了一个名为`mydatabase`的数据库,其中包含一个名为`mytable`的表。你需要替换代码中的数据库URL、用户名和密码,以及表名和字段名,以适应你的实际情况。 通过计算偏移量`(currentPage - 1) * pageSize`,我们可以确定从哪一行开始返回结果。然后,我们使用`LIMIT`子句限制返回的结果数量为`pageSize`。 希望这个示例对你有帮助!如果还有其他问题,随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值