MySQL limit N offset M 速度慢?来实际体验下

直接开始

有一张表:trade_user,表结构如下:


mysql> desc trade_user;
+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| id         | bigint unsigned  | NO   | PRI | NULL    | auto_increment |
| name       | varchar(20)      | NO   | MUL | NULL    |                |
| email      | longtext         | YES  |     | NULL    |                |
| age        | tinyint unsigned | YES  |     | NULL    |                |
| birthday   | datetime         | YES  |     | NULL    |                |
| created_at | datetime         | YES  |     | NULL    |                |
| updated_at | datetime         | YES  |     | NULL    |                |
| id_no      | char(18)         | NO   |     |         |                |
+------------+------------------+------+-----+---------+----------------+
8 rows in set (0.02 sec)

COPY

表行数


mysql> select count(*) from trade_user;
+----------+
| count(*) |
+----------+
|  3536655 |
+----------+
1 row in set (0.60 sec)

COPY

无索引limit n offset m

OFFSET 0:limit 10 offset 0

 select  * from trade_user order by email limit 10 offset 0;

COPY

执行耗时:1.41 秒

file

OFFSET 1万: limit 10 offset 10000


select  * from trade_user order by email limit 10 offset 10000;

COPY

执行耗时: 1.68秒

file

OFFSET:10万:limit 10 offfet 100000


select  * from trade_user order by email limit 10 offset 100000;

COPY

执行耗时:1.89秒

file

OFFSET:100万:limit 10 offset 1000000


select  * from trade_user order by email limit 10 offset 1000000;

COPY

执行耗时:4.06秒

file

OFFSET:200万:limit 10 offset 2000000


select  * from trade_user order by email limit 10 offset 2000000;

COPY

执行耗时:9.07秒

file

有索引limit n offset m

trade_user表的name列有一个普通索引。

OFFSET 0:limit 10 offset 0

 select  * from trade_user order by name limit 10 offset 0;

COPY

执行耗时:0.01 秒

file

OFFSET 200万:limit 10 offset 2000000

 select  * from trade_user order by name limit 10 offset 2000000;

COPY

执行耗时:7.21 秒

file

为什么?

OFFSET越大,MySQL扫描行数越多:


+----+-------------+------------+------------+------+---------------+------+---------+------+---------+----------+----------------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra          |
+----+-------------+------------+------------+------+---------------+------+---------+------+---------+----------+----------------+
|  1 | SIMPLE      | trade_user | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 3447992 |   100.00 | Using filesort |
+----+-------------+------------+------------+------+---------------+------+---------+------+---------+----------+----------------+
1 row in set, 1 warning (0.00 sec)

COPY


| EXPLAIN| -> Limit/Offset: 10/2000000 row(s)  (cost=359470 rows=10) (actual time=8737..8737 rows=10 loops=1)-> Sort row IDs: trade_user.`name`, limit input to 2000010 row(s) per chunk  (cost=359470 rows=3.45e+6) (actual time=2552..8699 rows=2e+6 loops=1)-> Table scan on trade_user  (cost=359470 rows=3.45e+6) (actual time=0.0247..1870 rows=3.54e+6 loops=1)|
1 row in set (8.74 sec)

COPY

总结

在对大表进行 LIMIT 和 OFFSET 操作时,随着偏移量(OFFSET)的增加,性能会显著下降。由于 MySQL 必须首先跳过 OFFSET 之前的所有行,才能获取到 LIMIT 指定的数据量,因此当 OFFSET 值较大时,这会导致显著的性能开销,尤其是在没有对排序列添加索引的情况下。通过性能测试得出,即使 LIMIT 的值相同,越大的 OFFSET 会使 MySQL 扫描的行数越多,因此执行时间越长。

性能测试的总结如下:

  • 当没有索引支持 ORDER BY 子句时,即使是小范围的 LIMIT 查询,随着 OFFSET 的增加,查询性能会急剧下降。从测试结果来看,相同的 LIMIT 值下,OFFSET 值为 0 时查询耗时为 1.41 秒,而 OFFSET 值为 200 万时耗时增加到了 9.07 秒。
  • 当存在索引支持 ORDER BY 子句时,查询性能显著提升,OFFSET 为 0 时耗时只需 0.01 秒。这表明,有索引的情况下,小 OFFSET 值查询的性能提升非常明显。但即使有索引支持,大 OFFSET 值仍然会导致较高的性能开销,如 OFFSET 值为 200 万时耗时为 7.21 秒。
  • 测试中观察到的性能差异主要是由于 MySQL 在未使用索引的情况下需要对所有数据进行全表扫描,并使用文件排序来找到 ORDER BY 子句中指定的顺序,然后才能跳过 OFFSET 指定的行。

为了优化大表的 LIMIT 和 OFFSET 查询:

  • 避免使用大的 OFFSET 值,特别是在没有对 ORDER BY 的字段进行索引优化的情况下。
  • 考虑使用 "keyset pagination" 或 "seek method" 方法,即通过跟踪上一次检索的最后一个记录的标识,来避免使用 OFFSET
  • 确保 ORDER BY 中的列上有适当的索引以提高排序和检索效率。
  • 尽量减少查询结果中的列数,只取需要的列。
  • 如果有可能,调整应用逻辑以减少数据量,或将常用查询结果进行缓存。

大表不用使用大OFFSET。

参考

MySQL limit N offset M 速度慢?来实际体验下 – 小厂程序员

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

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

相关文章

第十届蓝桥杯省赛真题(C/C++大学B组)

目录 试题 A: 组队 试题 B: 年号字串 试题 C: 数列求值 试题 D: 数的分解 试题 E: 迷宫 试题 F: 特别数的和 试题 G:完全二叉树的权值 试题 H:等差数列 试题 I:后缀表达式(不一定对) 试题 J:灵能…

数据库的事务的并发问题和四种隔离级别

1. 数据并发问题 MySQL是一个客户端/服务器架构的软件,可以有若干个客户端与之连接,连接上之后,就可以称之为一个会话(Session),对于服务器来说可能同时处理多个Session,也就是对服务器来说可能…

element-ui中el-radio-group组件绑定点击事件触发多次的解决办法

1、需求 电商首页需求,需要做个单选框,然后点击选中切换图标方向及更换价格升倒序,如下图: 从官网文档看,单选框支持change event,使用click加载按钮处不会触发选中 但是使用 click.native 事件不做处理…

LeetCode 2924.找到冠军 II:脑筋急转弯——只关心入度

【LetMeFly】2924.找到冠军 II:脑筋急转弯——只关心入度 力扣题目链接:https://leetcode.cn/problems/find-champion-ii/ 一场比赛中共有 n 支队伍,按从 0 到 n - 1 编号。每支队伍也是 有向无环图(DAG) 上的一个节…

The C programming language (second edition,KR) exercise(CHAPTER 2)

E x c e r c i s e 2 − 1 Excercise\quad 2-1 Excercise2−1&#xff1a;输出结果如图1和图2所示&#xff0c;这道练习题需要文章1和文章2的知识。 #include <stdio.h> #include <limits.h>float getFloat(char sign, unsigned char exp, unsigned mantissa); do…

【Django开发】0到1美多商城项目md教程第7篇:登录,1. 互联开发者申请步骤【附代码文档】

美多商城完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;欢迎来到美多商城&#xff01;&#xff0c;项目准备。展示用户注册页面&#xff0c;创建用户模块子应用。用户注册业务实现&#xff0c;用户注册前端逻辑。图形验证码&#xff0c;图形验证码接口设…

代码随想录算法训练营第二十五天|216.组合总和III、17.电话号码的字母组合

216. 组合总和 III 思路&#xff1a; 本题就是在[1,2,3,4,5,6,7,8,9]这个集合中找到和为n的k个数的组合。 相对于 77. 组合&#xff0c;无非就是多了一个限制&#xff0c;本题是要找到和为n的k个数的组合&#xff0c;而整个集合已经是固定的了[1,...,9]。 本题k相当于树的深…

vue列表列表过滤

对已知的列表进行数据过滤(根据输入框里面的内容进行数据过滤) 编写案例 通过案例来演示说明 效果就是这样的 输入框是模糊查询 想要实现功能&#xff0c;其实就两大步&#xff0c;1获取输入框内容 2根据输入内容进行数据过滤 绑定收集数据 我们可以使用v-model去双向绑定 …

Java 使用 ant.jar 执行 SQL 脚本文件

Java 使用 ant.jar 执行 SQL 脚本文件&#xff0c;很简单。 在 pom.xml 中导入 ant 依赖 <dependency><groupId>org.apache.ant</groupId><artifactId>ant</artifactId><version>1.10.11</version> </dependency>sql 脚本文件…

【2024】使用Rancher管理k8s集群和创建k8s集群

Rancher管理k8s集群及创建k8s集群。 Rancher版本为:2.8.2目录 rancher管理k8s集群rancher创建k8s集群rancher管理k8s集群 使用rancher管理已经存在的k8s集群。 本部分内容需要自行准备好k8s集群及rancher平台,部署请看本人其他文章 。 登录到rancher平台后,点击集群管理,…

c++修炼之路之vector模拟实现

目录 前言&#xff1a; 一&#xff1a;在STL的开源代码中的vector的实现 二&#xff1a;模拟实现 1.数据成员size()capacity() 2.resizereserve 3.构造函数析构函数赋值重载 4.迭代器[] 5.push_backinserterase迭代器失效问题 三&#xff1a;测试用例和全部代码 接下…

【LAMMPS学习】八、基础知识(1.8)键的断裂

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

【C++庖丁解牛】哈希表/散列表的设计原理 | 哈希函数

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1.哈希概念2.哈希冲突…

推荐七个Python效率工具!

为了提高效率&#xff0c;我们在平时工作中常会用到一些Python的效率工具&#xff0c;Python作为比较老的编程语言&#xff0c;它可以实现日常工作的各种自动化。为了更便利的开发项目&#xff0c;这里给大家推荐几个Python的效率工具。 1、Pandas-用于数据分析 Pandas是一个强…

复杂DP算法(动态规划)

复杂DP算法 一、线性DP例题1、鸣人的影分身题目信息思路题解 2、糖果题目信息思路题解 二、区间DP例题密码脱落题目信息思路题解 三、树状DP例题生命之树题目信息思路题解 一、线性DP 例题 1、鸣人的影分身 题目信息 思路 题解 #include <bits/stdc.h> #define endl …

ZISUOJ 数据结构-线性表

题目列表&#xff1a; 问题 A: 逆序链表建立 思路&#xff1a; 可以使用头插法插入所有元素后正序遍历输出或者使用尾插法逆序遍历&#xff0c;推荐使用双链表。这是链表系列的第一个题&#xff0c;那这个题下面的参考题解的各种解法我会尽可能写全一些。 参考题解1&#xff0…

【OTA】STM32-OTA升级——持续更新

【OTA】STM32-OTA升级——持续更新 文章目录 前言一、ymodem串口协议1、Ymodem 协议2、PC3、蓝牙4、WIFI云平台 二、UDS车载协议1.UDS协议 总结 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、ymodem串口协议 1、Ymodem 协议 STM32 Ymodem …

【I/O】基于事件驱动的 I/O 模型---Reactor

Reactor 模型 BIO 到 I/O 多路复用 为每个连接都创建一个线程 假设我们现在有一个服务器&#xff0c;想要对接多个客户端&#xff0c;那么最简单的方法就是服务端为每个连接都创建一个线程&#xff0c;处理完业务逻辑后&#xff0c;随着连接关闭线程也要销毁&#xff0c;但是…

每日一题(leetcode238):除自身以外数组的乘积--前缀和

不进阶是创建两个数组&#xff1a; class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int nnums.size();vector<int> left(n);vector<int> right(n);int mul1;for(int i0;i<n;i){mul*nums[i];left[i]mul;}mul1;for…

前端开发攻略---根据音频节奏实时绘制不断变化的波形图。深入剖析如何通过代码实现音频数据的可视化。

1、演示 2、代码分析 逐行解析 JavaScript 代码块&#xff1a; const audioEle document.querySelector(audio) const cvs document.querySelector(canvas) const ctx cvs.getContext(2d)这几行代码首先获取了 <audio> 和 <canvas> 元素的引用&#xff0c;并使用…