Mysql的深度分页查询优化

一、深度分页为什么慢?

当执行 SELECT * FROM orders ORDER BY id LIMIT 1000000, 10 时:

  • MySQL 会扫描前 1,000,010 行,丢弃前 100 万行,仅返回 10 行。
  • 偏移量(offset)越大,扫描行数越多,时间复杂度为 O(N+M)(N = 偏移量,M = 每页条数)。

核心痛点LIMIT 本质是 “跳过” 数据,而非 “直接定位”,导致全表扫描。

二、5 大优化方案(按优先级排序)

🔍 方案 1:覆盖索引 + 延迟关联(通用最优解)

原理:先通过索引定位主键,再批量回表,减少无效扫描。
实现

sql

-- 1. 创建覆盖索引(包含排序字段+主键)
ALTER TABLE orders ADD INDEX idx_created_at_id (created_at, id);-- 2. 优化查询(子查询只查索引,主查询回表)
SELECT o.* 
FROM orders o
INNER JOIN (SELECT id  -- 仅需主键(覆盖索引)FROM orders ORDER BY created_at, id  -- 利用索引排序LIMIT 1000000, 10  -- 仅扫描 10 行索引
) AS tmp ON o.id = tmp.id;

效果:扫描行数从 1,000,010 降至 10,速度提升 10 万倍!
适用场景:所有带排序的分页(如订单、日志)。

📌 方案 2:游标分页(适合连续翻页)

原理:记录上一页最后一条的 id,避免 OFFSET
示例

sql

-- 第 1 页(初始查询)
SELECT * FROM orders ORDER BY id DESC LIMIT 10;  -- 假设最后一条 id=1000-- 第 2 页(基于游标)
SELECT * 
FROM orders 
WHERE id < 1000  -- 定位起始点
ORDER BY id DESC 
LIMIT 10;  -- 仅扫描 10 行

优点:时间复杂度 O(M),与页码无关;适合无限滚动(如抖音刷视频)。
缺点:不支持随机跳页(如直接跳转到第 1000 页)。

🗂️ 方案 3:范围分片(依赖有序数据)

原理:按时间 / ID 分段,缩小查询范围。
示例

sql

-- 按月份分区查询(假设数据按月递增)
SELECT * 
FROM orders 
WHERE created_at BETWEEN '2023-10-01' AND '2023-10-31'
ORDER BY id 
LIMIT 10;

适用场景:时间序列数据(如报表、日志),用户可接受 “按范围筛选”。

💡 方案 4:预计算分页(冷数据专用)

原理:提前计算分页书签,存入汇总表。
实现

sql

-- 创建汇总表(每日凌晨更新)
CREATE TABLE order_pager (page_num INT PRIMARY KEY,min_id BIGINT,max_id BIGINT
);-- 插入分页书签(每页 100 条)
INSERT INTO order_pager
SELECT FLOOR((id-1)/100) + 1 AS page_num,MIN(id) AS min_id,MAX(id) AS max_id
FROM orders
GROUP BY page_num;-- 查询第 1000 页
SELECT * 
FROM orders 
WHERE id BETWEEN (SELECT min_id FROM order_pager WHERE page_num=1000) AND (SELECT max_id FROM order_pager WHERE page_num=1000)
LIMIT 100;

优点:查询时间稳定,适合历史数据(如年报);缺点:存储冗余。

🚀 方案 5:Elasticsearch 兜底(海量数据)

原理:利用 ES 的 search_after 避免深度分页性能衰减。
示例

json

GET /orders/_search
{"size": 10,"sort": ["_id"],  -- 按主键排序"search_after": [1000000],  -- 上一页最后一条的 _id"query": { ... }
}

适用场景:百万级以上数据,需复杂查询(如全文搜索)。

三、索引设计黄金法则

场景索引建议示例
时间 + 主键排序复合索引(时间,主键)(created_at, id)
多条件过滤 + 排序最左匹配索引(WHERE > ORDER BY)(status, created_at, id)
字符串排序前缀索引(平衡长度与选择性)name(20) (取前 20 字符)

⚠️ 注意:索引非越多越好,单表索引不超过 5 个,避免冗余。

四、方案对比与选择指南

方案时间复杂度适用场景推荐指数
覆盖索引 + 延迟关联O(M)通用场景(90% 业务首选)⭐⭐⭐⭐⭐
游标分页O(M)连续翻页(如 App 列表)⭐⭐⭐⭐
预计算分页O(1)冷数据历史查询⭐⭐⭐
ElasticsearchO(logN)海量数据 + 复杂查询⭐⭐⭐⭐

决策树

  1. 数据量 < 10 万:直接 LIMIT,无需优化。
  2. 10 万~100 万:方案 1(覆盖索引)。
  3. 100 万~1000 万:方案 1 + 方案 2(游标)。
  4. 千万级以上:方案 5(ES)+ 方案 1 兜底。

五、实战避坑指南

  1. ** 避免 SELECT ***:只查必要字段,减少回表数据量。
  2. 监控执行计划

    sql

    EXPLAIN SELECT * FROM orders ...;  -- 重点看 `rows` 列,理想值接近 LIMIT 数量。
    
  3. 慢查询日志:捕获真实慢查询(如 LIMIT 500000,10 超过 1 秒)。
  4. 业务妥协:限制最大分页深度(如 App 最多显示 500 页),避免极端场景。

总结

深度分页的核心优化思路是 “跳过扫描,直接定位”

  • 热数据:用覆盖索引 + 延迟关联,确保每次查询只扫描少量索引。
  • 冷数据:预计算分页或归档到 ES,牺牲空间换时间。
  • 业务层:结合游标分页和分页深度限制,避免数据库被拖垮。

通过这一套组合拳,可将深度分页的耗时从 “秒级” 优化到 “毫秒级”,轻松应对百万级数据分页!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/77038.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最新扣子(Coze)案例教程:Excel数据生成统计图表,自动清洗数据+转换可视化图表+零代码,完全免费教程

大家好&#xff0c;我是斜杠君。 知识星球群有同学和我说每天的工作涉及很多数据表的重复操作&#xff0c;想学习Excel数据表通过大模型自动转数据图片的功能。 今天斜杠君就带大家一起搭建一个智能体&#xff0c;以一个销售行业数据为例&#xff0c;可以快速实现自动清洗Exc…

Uniapp 中缓存操作指南

在 Uniapp 中,你可以使用三种方式操作缓存:同步方法、异步方法和 Vuex 持久化存储。以下是详细的设置、获取和清除缓存的方法: 1. 同步方法 设置缓存 uni.setStorageSync(key, value); // 示例 uni.setStorageSync(token, abc123); 获取缓存 const value = uni.getStor…

k8s的yaml文件里的volume跟volumeMount的区别

volume 是 Pod 级别的资源&#xff0c;用于定义存储卷。它是一个独立于容器的存储资源&#xff0c;可以被一个或多个容器共享使用。volume 的定义位于 Pod 的 spec.volumes 部分。 特点 独立性&#xff1a;volume 是 Pod 的一部分&#xff0c;而不是容器的一部分。它独立于容…

梅毒单阳能否通过国企体检?

国企体检通常会参照公务员体检标准进行&#xff0c;梅毒检测是其中的常规项目。 一、明确“梅毒单阳”的定义 检测指标解析 TPPA阳性RPR阴性&#xff1a;可能为既往感染已治愈&#xff0c;或极早期/晚期梅毒&#xff1b; RPR阳性TPPA阴性&#xff1a;需警惕假阳性&#xff08…

Python 爬虫实战 | 企名科技

文章目录 一、企名科技1、目标网站2、网站特点3、确定解密位置4、扣js代码 一、企名科技 1、目标网站 网址&#xff1a;https://wx.qmpsee.com/articleDetail?idfeef62bfdac45a94b9cd89aed5c235be目标数据&#xff1a;获取消费行业研究下面的13篇文章数据 2、网站特点 服…

Pikachu靶场

本质是信任了不可信的客户端输入。防御核心&#xff1a; 永不信任客户端提交的权限参数&#xff08;如 user_id, role&#xff09;。强制服务端校验用户身份与操作权限。定期审计权限模型&#xff0c;避免业务迭代引入新漏洞。 水平越权 1&#xff0c;按照网站的提示要求登录 进…

C++区别于C语言的提升用法(万字总结)

1.namespace产生原因 在C语言中&#xff0c;变量&#xff0c;函数&#xff0c;以至于类都是大量存在的&#xff0c;因此会产生大量的名称存在于全局作用域中&#xff0c;可能产生很多冲突&#xff0c;至此c的祖师爷为避免命名冲突和名字的污染&#xff0c;造出来了关键字names…

数据库day-07

一、实验名称和性质 子查询 验证 设计 二、实验目的 1&#xff0e;掌握子查询的嵌套查询&#xff1b; 2.掌握集合操作 3&#xff0e;了解EXISTS嵌套查询方法&#xff1b; 三、实验的软硬件环境要求 硬件环境要求&#xff1a; PC机(单机) 使用的软件名称、版本号以及模块…

【前端】【业务场景】【面试】在前端开发中,如何实现文件的上传与下载功能,并且处理可能出现的错误情况?

前端文件上传与下载攻略 本文目标&#xff1a;帮你快速掌握文件上传 & 下载的核心实现方式&#xff0c;并在常见出错场景下保持“优雅不崩溃”。 一、文件上传 1. 基础结构 <input type"file" id"fileInput" /> <button id"uploadBtn&…

Kafka 消息积压监控和报警配置的详细步骤

Kafka 消息积压监控和报警配置的详细步骤示例&#xff0c;涵盖常用工具&#xff08;如 Prometheus Grafana、云服务监控&#xff09;和自定义脚本方法&#xff1a; 一、监控配置 方法1&#xff1a;使用 Prometheus Grafana kafka-exporter 步骤1&#xff1a;部署 kafka-ex…

【C++】内存管理:内存划分、动态内存管理(new、delete用法)

文章目录 一、C/C中的内存划分二、C语言中动态内存管理方式三、C中动态内存管理方式1、new、delete基本用法(1)、内置类型(2)、自定义类型 2、operator new与operator delete函数3、new和delete的实现原理&#xff08;1&#xff09;内置类型&#xff08;2&#xff09;自定义类型…

C# 实战_RichTextBox选中某一行条目高亮,离开恢复

C# 中控件richtextbox中某一行的条目内容高亮&#xff0c;未选中保持不变。当鼠标点击某一行的条目高亮&#xff0c;离开该条目就恢复默认颜色。 运行效果&#xff1a; 核心代码实现功能&#xff1a; //高亮指定行的方法private void HighlightLine(RichTextBox rtb,int lineI…

Vue3 ref与props

ref 属性 与 props 一、核心概念对比 特性ref (标签属性)props作用对象DOM 元素/组件实例组件间数据传递数据流向父组件访问子组件/DOM父组件 → 子组件响应性直接操作对象单向数据流&#xff08;只读&#xff09;使用场景获取 DOM/调用子组件方法组件参数传递Vue3 变化不再自…

视频汇聚平台EasyCVR赋能高清网络摄像机:打造高性价比视频监控系统

在现代视频监控系统中&#xff0c;高清网络摄像机作为核心设备&#xff0c;其性能和配置直接影响监控效果和整体系统的价值。本文将结合EasyCVR视频监控的功能&#xff0c;探讨如何在满足使用需求的同时&#xff0c;优化监控系统的设计&#xff0c;降低项目成本&#xff0c;并提…

【C++】 —— 笔试刷题day_21

一、爱丽丝的人偶 题目解析 现在存在n个玩偶&#xff0c;每个玩偶的身高是1、2、3......n&#xff1b; 现在我们要对这些玩偶进行排序&#xff08;如果x人偶&#xff0c;它左右两边的玩偶一个比x高、一个比x矮&#xff0c;那这个玩偶就会爆炸&#xff09;。 我们不想要任何一个…

详解.vscode 下的json .vscode文件夹下各个文件的作用

1.背景 看一些开源项目的时候,总是看到vscode先有不同的json文件,再次做一下总结方便之后查看 settings.json肯定不用多说了 vscode 编辑器分为 全局用户配置 和 当前工作区配置 那么.vscode文件夹下的settings.json文件夹肯定就是当前工作区配置了 在此文件对单个的项目进行配…

手动实现legend 与 echarts图交互 通过js事件实现图标某项的高亮 显示与隐藏

通过html实现legend的样式 提供调用echarts的api实现与echarts图表交互的效果 实现饼图element实现类似于legend与echartstu表交互效果 效果图 配置代码 <template><div style"height: 400px; width: 500px;background-color: #CCC;"><v-chart:opti…

Spring Boot 配置源详解(完整版)

Spring Boot 配置源详解&#xff08;完整版&#xff09; 一、配置源加载顺序与优先级 配置源类型优先级顺序&#xff08;从高到低&#xff09;对应配置类/接口是否可覆盖典型文件/来源命令行参数&#xff08;--keyvalue&#xff09;1&#xff08;最高&#xff09;SimpleComman…

【无人机】无人机遥控器设置与校准,飞行模式的选择,无线电控制 (RC) 设置

目录 1、遥控器校准 1.1、校准步骤 2、飞行模式选择&#xff0c;遥控器通道映射 2.1、配置步骤 1、遥控器校准 在校准无线电系统之前&#xff0c;必须连接/绑定接收器和发射器。绑定发射器和接收器对的过程是特定于硬件的&#xff08;有关说明&#xff0c;请参阅 RC 手册&…

Redis 有序集合 ZSet 深度解析教程

Redis-ZSet 引言一、 ZSet 核心概念与特性1.1 什么是 ZSet&#xff1f;1.2 ZSet 与 Set、List 的本质区别 二、 ZSet 典型应用场景2.1 排行榜 (Leaderboards)2.2 带权重的任务队列 / 延迟队列2.3 时间轴 (Timeline)2.4 范围查找 三、 ZSet 底层实现3.1 ziplist (压缩列表)3.2 s…