当前位置: 首页 > news >正文

MySQL 如何深度分页问题

在实际的数据库应用场景中,我们常常会遇到需要进行分页查询的需求。对于少量数据的分页查询,MySQL 可以轻松应对。然而,当我们需要进行深度分页(即从大量数据的中间位置开始获取少量数据)时,就会面临性能严重下降的问题。本文将深入探讨 MySQL 深度分页的问题,并介绍子查询和滚动 ID 这两种有效的解决方式。

深度分页问题背景

深度分页通常是指使用 LIMIT m, n 语句进行查询,其中 m 是偏移量,n 是要返回的记录数。当 m 的值非常大时,就会出现深度分页的情况。例如:

select * from user where sex='女' order by age limit 100000000, 10;

这条 SQL 语句的目的是从 user 表中筛选出性别为女的记录,按照年龄排序,然后跳过前面的 100000000 条记录,返回接下来的 10 条记录。

深度分页性能问题原因

LIMIT 主要在 Server 层执行,而不是存储引擎层。在 Server 层,执行器调用存储引擎 API 获取数据时,会先获取到全部符合条件的数据,然后在发送给客户端的时候才会进行 LIMIT 操作。具体来说,Server 层在执行上述 SQL 时,每获取到一条数据,会查看该数据是否是第 100000001 条数据,如果不是,就不会发送到客户端,只进行 limit_count 计数,直到获取到第 100000001 条数据才开始发送到客户端。

此外,如果查询的字段需要回表扫描,每一次查询都会拿着 age 列的二级索引查到的主键值去回表。对于 LIMIT 10000000, 10 这样的查询,就会回表 10000000 次,效率极低。我们可以使用 EXPLAIN 查看查询计划来进一步分析:

explain select * from user where sex = '女' order by age limit 10000000, 10;

会发现这条记录通常不会走age索引,而是选择全表扫描+文件排序,这是因为优化器认为选择age的效率甚至比不上全表扫描+文件排序
所以当翻页靠后时,查询会变得很慢,因为随着偏移量的增加,我们需要排序和扫描的非目标行数据也会越来越多,这些数据再扫描后都会被丢弃。

解决深度分页问题的方法

子查询优化

子查询优化的核心思想是先在二级索引上获取需要的主键 ID,然后再根据这些 ID 去主键索引中获取完整的数据,避免了直接在主键索引上进行大量的偏移操作。

示例代码如下:

SELECT * 
FROM USER 
WHERE sex = '女' AND id >= (SELECT id FROM USER WHERE sex = '女' ORDER BY age LIMIT 10000000,1) 
ORDER BY age LIMIT 10;

在这个查询中,子查询 SELECT id FROM user WHERE sex = ‘女’ ORDER BY age LIMIT 10000000, 1 会在 age 列的二级索引上操作,由于二级索引只包含索引列和主键值,数据量相对较小,跳过 10000000 条记录的开销也会小很多。主查询再根据子查询返回的 id 在主键索引上定位到起始位置,获取接下来的 10 条记录,减少了扫描的数据量和回表次数,从而提高了查询性能。

滚动 ID 方式

滚动 ID 方式不支持跳页,但可以在顺序分页的场景下有效解决深度分页问题。其原理是记录上一页的最后一条记录的 ID,然后在查询下一页时,只查询 ID 大于该记录 ID 的数据。

示例代码如下:

假设上一页的最后一条记录的 ID 是 last_id:

SELECT * FROM user WHERE sex = '女'  AND id > last_id ORDER BY age LIMIT 10;

在实际应用中,当用户请求第一页数据时,正常执行查询:

SELECT * FROM user WHERE sex = '女' ORDER BY age LIMIT 10;

记录下这一页的最后一条记录的 ID,当用户请求下一页数据时,使用上述滚动 ID 的查询语句。这种方式避免了大量的偏移操作,每次查询只需要从上次记录的 ID 之后开始扫描,大大提高了查询效率。

总结

深度分页是 MySQL 中一个常见且棘手的问题,使用子查询和滚动 ID 这两种方式可以在不同的场景下有效解决该问题。子查询适用于需要跳页的场景,通过在二级索引上操作减少回表次数和扫描数据量;滚动 ID 方式适用于顺序分页的场景,通过记录上一页的最后一条记录的 ID 避免大量的偏移操作。在实际应用中,我们需要根据具体的业务需求选择合适的解决方案。

相关文章:

MySQL 如何深度分页问题

在实际的数据库应用场景中,我们常常会遇到需要进行分页查询的需求。对于少量数据的分页查询,MySQL 可以轻松应对。然而,当我们需要进行深度分页(即从大量数据的中间位置开始获取少量数据)时,就会面临性能严…...

1.攻防世界easyphp

进入题目页面如下 是一段PHP代码进行代码审计 <?php // 高亮显示PHP文件源代码 highlight_file(__FILE__);// 初始化变量$key1和$key2为0 $key1 0; $key2 0;// 从GET请求中获取参数a的值&#xff0c;并赋值给变量$a $a $_GET[a]; // 从GET请求中获取参数b的值&#xff…...

深度学习 Pytorch 神经网络的学习

本节将从梯度下降法向外拓展&#xff0c;介绍更常用的优化算法&#xff0c;实现神经网络的学习和迭代。在本节课结束将完整实现一个神经网络训练的全流程。 对于像神经网络这样的复杂模型&#xff0c;可能会有数百个 w w w的存在&#xff0c;同时如果我们使用的是像交叉熵这样…...

如何利用天赋实现最大化的价值输出-补

原文&#xff1a; https://blog.csdn.net/ZhangRelay/article/details/145408621 ​​​​​​如何利用天赋实现最大化的价值输出-CSDN博客 如何利用天赋实现最大化的价值输出-CSDN博客 引用视频差异 第一段视频目标明确&#xff0c;建议也非常明确。 录制视频的人是主动性…...

Vue简介

目录 Vue是什么&#xff1f;为什么要使用Vue&#xff1f;Vue的三种加载方式拓展&#xff1a;什么是渐进式框架&#xff1f; Vue是什么&#xff1f; Vue是一套用于构建用户界面的渐进式 JavaScript (主张最少)框架 &#xff0c;开发者只需关注视图层。另一方面&#xff0c;当与…...

three.js+WebGL踩坑经验合集(6.2):负缩放,负定矩阵和行列式的关系(3D版本)

本篇将紧接上篇的2D版本对3D版的负缩放矩阵进行解读。 (6.1):负缩放&#xff0c;负定矩阵和行列式的关系&#xff08;2D版本&#xff09; 既然three.js对3D版的负缩放也使用行列式进行判断&#xff0c;那么&#xff0c;2D版的结论用到3D上其实是没毛病的&#xff0c;THREE.Li…...

使用 OpenResty 构建高效的动态图片水印代理服务20250127

使用 OpenResty 构建高效的动态图片水印代理服务 在当今数字化的时代&#xff0c;图片在各种业务场景中广泛应用。为了保护版权、统一品牌形象&#xff0c;动态图片水印功能显得尤为重要。然而&#xff0c;直接在后端服务中集成水印功能&#xff0c;往往会带来代码复杂度增加、…...

Kafka下载

一、Kafka下载 下载地址&#xff1a;https://kafka.apache.org/downloads 二、Kafka安装 因为选择下载的是 .zip 文件&#xff0c;直接跳过安装&#xff0c;一步到位。 选择在任一磁盘创建空文件夹&#xff08;不要使用中文路径&#xff09;&#xff0c;解压之后把文件夹内容…...

【C++语言】卡码网语言基础课系列----5. A+B问题VIII

文章目录 练习题目AB问题VIII具体代码实现 小白寄语诗词共勉 练习题目 AB问题VIII 题目描述&#xff1a; 你的任务是计算若干整数的和。 输入描述&#xff1a; 输入的第一行为一个整数N&#xff0c;接下来N行每行先输入一个整数M&#xff0c;然后在同一行内输入M个整数。 输出…...

IP服务模型

1. IP数据报 IP数据报中除了包含需要传输的数据外&#xff0c;还包括目标终端的IP地址和发送终端的IP地址。 数据报通过网络从一台路由器跳到另一台路由器&#xff0c;一路从IP源地址传递到IP目标地址。每个路由器都包含一个转发表&#xff0c;该表告诉它在匹配到特定目标地址…...

仿真设计|基于51单片机的温湿度、一氧化碳、甲醛检测报警系统

目录 具体实现功能 设计介绍 51单片机简介 资料内容 仿真实现&#xff08;protues8.7&#xff09; 程序&#xff08;Keil5&#xff09; 全部内容 资料获取 具体实现功能 &#xff08;1&#xff09;温湿度传感器、CO传感器、甲醛传感器实时检测温湿度值、CO值和甲醛值进…...

QModbusTCPClient 服务器断开引起的程序崩溃

最近使用QModbusTCPClient 与一套设备通信&#xff0c;有一个QTimer频繁的通过读取设备寄存器。程序运行良好&#xff0c;但是有个问题&#xff1a;正常进行中设备断电了&#xff0c;整个程序都会崩溃。解决过程如下&#xff1a; 1.失败方案一 在QModbusTCPClient的errorOccu…...

Vue 3 30天精进之旅:Day 11 - 状态管理

在开发复杂的前端应用时&#xff0c;状态管理是一个不可或缺的部分。Vuex是Vue.js官方提供的状态管理库&#xff0c;能够高效地管理应用中的共享状态。它使得各个组件之间的状态共享和维护变得更加简单和清晰。今天&#xff0c;我们将探讨以下几个方面&#xff1a; Vuex概述安…...

npm 和 pip 安装中常见问题总结

安装路径的疑惑&#xff1a;NPM 和 PIP 的安装机制 NPM 安装路径规则&#xff1a; 依赖安装在项目目录下&#xff1a; 当你运行 npm install --save-dev jest&#xff0c;它会在当前目录&#xff08;例如 F:\&#xff09;下创建一个 node_modules 文件夹&#xff0c;把 jest 安…...

Flutter开发环境配置

下载 Flutter SDK 下载地址&#xff1a;https://docs.flutter.cn/get-started/install M1/M2芯片选择带arm64字样的Flutter SDK。 解压 cd /Applications unzip ~/Downloads/flutter_macos_arm64_3.27.3-stable.zip执行 /Applications/flutter/bin/flutterManage your Flut…...

Two Divisors ( Educational Codeforces Round 89 (Rated for Div. 2) )

Two Divisors &#xff08; Educational Codeforces Round 89 (Rated for Div. 2) &#xff09; You are given n n n integers a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1​,a2​,…,an​. For each a i a_i ai​ find its two divisors d 1 > 1 d_1 > 1 d1​…...

亚博microros小车-原生ubuntu支持系列:17 gmapping

前置依赖 先看下亚博官网的介绍 Gmapping简介 gmapping只适用于单帧二维激光点数小于1440的点&#xff0c;如果单帧激光点数大于1440&#xff0c;那么就会出【[mapping-4] process has died】 这样的问题。 Gmapping是基于滤波SLAM框架的常用开源SLAM算法。 Gmapping基于RBp…...

Java面试题2025-并发编程进阶(线程池和并发容器类)

线程池 一、什么是线程池 为什么要使用线程池 在开发中&#xff0c;为了提升效率的操作&#xff0c;我们需要将一些业务采用多线程的方式去执行。 比如有一个比较大的任务&#xff0c;可以将任务分成几块&#xff0c;分别交给几个线程去执行&#xff0c;最终做一个汇总就可…...

Stable Diffusion 3.5 介绍

Stable Diffusion 3.5 是由 Stability AI 推出的最新一代图像生成模型&#xff0c;是 Stable Diffusion 系列的重要升级版本。以下是关于 Stable Diffusion 3.5 的详细信息&#xff1a; 版本概述 Stable Diffusion 3.5 包含三个主要版本&#xff1a; Stable Diffusion 3.5 L…...

云计算部署模式全面解析

目录 引言公有云私有云混合云三种部署模式的对比选择建议未来趋势结语 1. 引言 随着云计算技术的快速发展,企业在选择云部署模式时面临着多种选择。本文将深入探讨云计算的三种主要部署模式:公有云、私有云和混合云,帮助读者全面了解它们的特点、优势及适用场景。 © iv…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...

FFmpeg avformat_open_input函数分析

函数内部的总体流程如下&#xff1a; avformat_open_input 精简后的代码如下&#xff1a; int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

macOS 终端智能代理检测

&#x1f9e0; 终端智能代理检测&#xff1a;自动判断是否需要设置代理访问 GitHub 在开发中&#xff0c;使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新&#xff0c;例如&#xff1a; fatal: unable to access https://github.com/ohmyzsh/oh…...

Unity VR/MR开发-VR开发与传统3D开发的差异

视频讲解链接&#xff1a;【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...

Python常用模块:time、os、shutil与flask初探

一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...

机器学习的数学基础:线性模型

线性模型 线性模型的基本形式为&#xff1a; f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法&#xff0c;得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...