MySQL解决深度分页问题的几种方案对比

 更新时间:2026年07月20日 08:51:28   作者:wuqingshun314159  
当电商订单数据达到5000万时,翻到第10000页查询明显变慢,本文深入剖析MySQL深度分页的性能瓶颈,详解子查询优化、游标分页和Elasticsearch的search_after三种实战方案,帮你轻松应对大数据量分页难题,提升后台查询效率,需要的朋友可以参考下

一、面试题

在电商后台的订单列表中,用户可以按下单时间倒序分页查询。当翻到第 10000 页时,SQL 查询明显变慢,如何分析和优化?

二、真实业务场景

订单表约有 5000 万条数据,后台查询最近订单:

SELECT id, order_no, user_id, amount, status, created_at
FROM orders
WHERE status = 1
ORDER BY id DESC
LIMIT 999900, 10;

LIMIT 999900, 10 并不是直接定位到第 999901 条数据,而是先扫描、排序并跳过前 999900 条记录,再返回 10 条数据。

页码越大,扫描的数据越多,性能越差,这就是深度分页问题。

三、方案一:子查询优化

先利用覆盖索引查询出当前页的主键,再根据主键回表查询完整数据:

SELECT id, order_no, user_id, amount, status, created_at
FROM orders
WHERE id IN (
    SELECT id
    FROM orders
    WHERE status = 1
    ORDER BY id DESC
    LIMIT 999900, 10
)
ORDER BY id DESC;

创建联合索引:

CREATE INDEX idx_status_id
ON orders(status, id);

子查询只查询 id,可以尽量利用覆盖索引,减少回表次数。

适合页码分页、需要跳转到指定页码的场景,但深度很大时,子查询仍然需要扫描前面的数据。

四、方案二:基于游标或最大 ID 分页

第一次查询:

SELECT id, order_no, user_id, amount, status, created_at
FROM orders
WHERE status = 1
ORDER BY id DESC
LIMIT 10;

假设本次返回的最小 ID 是 985000,下一页查询:

SELECT id, order_no, user_id, amount, status, created_at
FROM orders
WHERE status = 1
  AND id < 985000
ORDER BY id DESC
LIMIT 10;

创建索引:

CREATE INDEX idx_status_id
ON orders(status, id);

这种方式可以直接从索引位置继续读取,不需要扫描并丢弃前面的数据,性能基本不受页码影响。

但它只适合连续翻页,不适合用户直接跳转到第 10000 页。

五、排序字段不唯一时的写法

如果按照 created_at 倒序排序,多个订单可能拥有相同的创建时间,需要增加 id 作为唯一排序条件:

SELECT id, order_no, user_id, amount, status, created_at
FROM orders
WHERE status = 1
  AND (
      created_at < '2026-07-16 10:00:00'
      OR (
          created_at = '2026-07-16 10:00:00'
          AND id < 985000
      )
  )
ORDER BY created_at DESC, id DESC
LIMIT 10;

对应索引:

CREATE INDEX idx_status_created_id
ON orders(status, created_at, id);

其中 created_atid 组成稳定的排序游标,避免数据重复或遗漏。

六、方案三:使用 Elasticsearch

如果业务是商品搜索、订单搜索、日志检索等复杂查询,可以使用 Elasticsearch。

传统分页:

{
  "from": 999900,
  "size": 10
}

深度分页时仍然需要维护大量搜索结果,性能会下降。

推荐使用 search_after

{
  "size": 10,
  "query": {
    "term": {
      "status": 1
    }
  },
  "sort": [
    {
      "created_at": "desc"
    },
    {
      "id": "desc"
    }
  ],
  "search_after": [
    "2026-07-16T10:00:00",
    985000
  ]
}

search_after 需要携带上一页最后一条记录的排序值,适合连续翻页。

七、方案对比

方案优点缺点适用场景
LIMIT offset,size写法简单页码越大越慢数据量小
子查询减少回表数据深度很大时仍需扫描需要页码跳转
游标分页性能稳定不支持随机跳页无限滚动、连续翻页
Elasticsearch支持复杂搜索需要维护数据同步搜索、日志、订单检索

八、面试总结

解决 MySQL 深度分页问题,核心不是简单修改 LIMIT,而是减少数据库需要扫描和丢弃的数据量。

实际项目中通常这样选择:

  • 数据量较小:直接使用 LIMIT
  • 必须支持页码跳转:使用子查询和覆盖索引
  • 连续翻页或无限滚动:使用基于 ID 或时间的游标分页
  • 复杂搜索场景:使用 Elasticsearch 的 search_after
  • 排序字段不唯一:使用“排序字段 + 主键”构造稳定游标

以上就是MySQL解决深度分页问题的几种方案对比的详细内容,更多关于MySQL解决深度分页问题的资料请关注脚本之家其它相关文章!

相关文章

  • 分享Mysql命令大全

    分享Mysql命令大全

    本文给大家介绍mysql命令大全相关知识,涉及到mysql命令相关知识,对此感兴趣的朋友一起学习吧
    2015-12-12
  • 在Hadoop集群环境中为MySQL安装配置Sqoop的教程

    在Hadoop集群环境中为MySQL安装配置Sqoop的教程

    这篇文章主要介绍了在Hadoop集群环境中为MySQL安装配置Sqoop的教程,Sqoop一般被用于数据库软件之间的数据迁移,需要的朋友可以参考下
    2015-12-12
  • MySQL主从复制过滤配置的完整方案

    MySQL主从复制过滤配置的完整方案

    在实际生产环境中,MySQL 主从复制架构几乎是标配,但默认的全量同步往往会带来不必要的资源消耗,所以本文整理了一套完整的过滤配置实验方案,从环境准备到六种核心场景测试,需要的朋友可以参考下
    2026-03-03
  • mysql 关键词相关度排序方法详细示例分析

    mysql 关键词相关度排序方法详细示例分析

    以下是对mysql关键词相关度排序方法进行了详细的分析介绍,需要的朋友可以过来参考下
    2013-08-08
  • MySQL5.7.10 安装文档教程详解

    MySQL5.7.10 安装文档教程详解

    这篇文章主要介绍了MySQL5.7.10 安装文档教程详解,需要的朋友可以参考下
    2017-02-02
  • 关于MySQL自增ID的一些小问题总结

    关于MySQL自增ID的一些小问题总结

    这篇文章主要给大家总结介绍了关于MySQL自增ID的一些小问题,文中通过示例代码介绍的非常详细,对大家学习或者使用MySQL具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-11-11
  • MySQL复合查询的具体使用

    MySQL复合查询的具体使用

    本文介绍了MySQL复合查询的基本操作,包括多表查询和复杂条件查询,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-03-03
  • 查看MySQL初始密码并修改的正确方式

    查看MySQL初始密码并修改的正确方式

    这篇文章主要给大家介绍了关于查看MySQL初始密码并修改的正确方式,MySQL是一款广泛使用的开源关系型数据库管理系统,安装后找回初始密码是MySQL使用中的一个基础问题,需要的朋友可以参考下
    2023-10-10
  • MySQL 优化 index merge引起的死锁分析

    MySQL 优化 index merge引起的死锁分析

    这篇文章主要介绍了MySQL 优化 index merge引起的死锁分析,MySQL通过优化索引合并是遇到的死锁问题,下面具体分析需要的小伙伴可以参考一下
    2022-04-04
  • Win7、WinXP下MySql安装出错完全卸载的方法步骤

    Win7、WinXP下MySql安装出错完全卸载的方法步骤

    这篇文章主要介绍了Win7、WinXP下MySql安装出错完全卸载的方法步骤,本文给出详细的操作步骤,按本文方法清理后,重新安装,应该就不会有错误了,需要的朋友可以参考下
    2015-06-06

最新评论