MySQL深度分页优化问题

☆* o(≧▽≦)o *☆嗨~我是小奥🍹
📄📄📄个人博客:小奥的博客
📄📄📄CSDN:个人CSDN
📙📙📙Github:传送门
📅📅📅面经分享(牛客主页):传送门
🍹文章作者技术和水平有限,如果文中出现错误,希望大家多多指正!
📜 如果觉得内容还不错,欢迎点赞收藏关注哟! ❤️

文章目录

  • MySQL深度分页优化问题
  • 一、Limit使用
  • 二、深度分页优化
    • 2.1 范围查询
    • 2.2 子查询
    • 2.3 inner join 延迟关联
    • 2.4 覆盖索引

MySQL深度分页优化问题

一、Limit使用

limit子句可以用于强制select语句返回指定的记录数。

select 字段 from 表名 limit 参数1,参数2;
select 字段 from 表名 limit 参数2 offset 参数1;(为了与 PostgreSQL 兼容)
  • 参数1:指定第一个返回记录行的偏移量,从0开始
  • 参数2:指定返回记录行的最大数目

如果只给定一个参数,那么表示返回的最大记录行数目

如果第二个参数为-1,表示第一个参数的偏移量之后的所有的数据

二、深度分页优化

查询偏移量过大的场景我们称为深度分页,这会导致查询性能较低。比如下面的查询:

# 普通分页查询
test> select * from t_demo order by id limit 1000000, 10
[2024-01-18 20:26:41]396 ms (execution: 346 ms, fetching: 50 ms) 内检索到从 1 开始的 10

这条SQL在执行的过程中,通过非聚簇索引去查询主键,然后拿到主键再通过聚簇索引进行回表查询,查询到满足条件的1000010条数据,丢弃前面的1000000条,返回最后10条。

优化的思路也非常明确:

  • 减少回表的次数
  • 尽量通过索引来查询

2.1 范围查询

当可以保证 ID 的连续性时,根据 ID 范围进行分页是比较好的解决方案:

# 连续id时,根据id范围进行分页
test> select * from t_demo where id > 1000000 and id <= 1000010 order by id
[2024-01-18 20:26:41]69 ms (execution: 8 ms, fetching: 61 ms) 内检索到从 1 开始的 10
# 通过记录上次查询结果的最后一条记录的ID进行下一页的查询
test> select * from t_demo where id > 1000000 limit 10
[2024-01-18 20:26:41]76 ms (execution: 6 ms, fetching: 70 ms) 内检索到从 1 开始的 10

但是一般来说,实际生产中很少会去使用数据库的自增ID,所以这种优化方式的局限性比较大,而且也不是很有必要。

2.2 子查询

阿里《Java开发手册》中也有明确的优化方式:

在这里插入图片描述

我们先来看子查询,子查询的思路是:先查询出 limit 第一个参数对应的主键值,再根据这个主键值再去过滤并 limit,这样效率会高一点。

# 子查询
test> select * from t_demo where id >= (select id from t_demo limit 1000000, 1) limit 10
[2024-01-18 20:26:41]210 ms (execution: 177 ms, fetching: 33 ms) 内检索到从 1 开始的 10

不过,子查询的结果会先产生一张新的表,会影响数据库的性能,所以应该避免使用子查询,并且id>=(...) 也限制了ID必须是递增的,这同样不适用比较复杂的场景。

2.3 inner join 延迟关联

延迟关联的优化思路,跟子查询的优化思路其实是一样的:都是把条件转移到主键索引,然后减少回表。不同点是,延迟关联使用了 INNER JOIN 代替子查询。

# inner join 延迟关联
test> select t1.* from t_demo t1inner join (select id from t_demo limit 1000000, 1) t2on t1.id >= t2.idlimit 10
[2024-01-18 20:26:42]211 ms (execution: 181 ms, fetching: 30 ms) 内检索到从 1 开始的 10

2.4 覆盖索引

索引中已经包含了所有需要获取的字段的查询方式称为覆盖索引。

# 覆盖索引
test> select id, a, b from t_demoorder by alimit 1000000, 10
[2024-01-18 20:26:42]279 ms (execution: 248 ms, fetching: 31 ms) 内检索到从 1 开始的 10

覆盖索引的好处:

  • 避免 InnoDB 表进行索引的二次查询,也就是回表操作: InnoDB 是以聚集索引的顺序来存储的,对于 InnoDB 来说,二级索引在叶子节点中所保存的是行的主键信息,如果是用二级索引查询数据的话,在查找到相应的键值后,还要通过主键进行二次查询才能获取我们真实所需要的数据。而在覆盖索引中,二级索引的键值中可以获取所有的数据,避免了对主键的二次查询 ,减少了 IO 操作,提升了查询效率。
  • 可以把随机 IO 变成顺序 IO 加快查询效率: 由于覆盖索引是按键值的顺序存储的,对于 IO 密集型的范围查找来说,对比随机从磁盘读取每一行的数据 IO 要少的多,因此利用覆盖索引在访问时也可以把磁盘的随机读取的 IO 转变成索引查找的顺序 IO。

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

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

相关文章

广告投放场景中ABtest分析的评价、优化和决策建议

目录 写在开头1. AB测试基础知识1.1 AB测试概述1.2 原理和流程1.3 广告领域中的AB测试应用 2. 评价广告投放中的AB测试2.1 关键指标选择与解释2.2 统计学方法应用 3. AB测试分析中的常见问题与解决方案3.1 样本偏差3.2 季节性影响3.3 测试时长选择3.4 结果误解与分析失误 4. 优…

老师布置作业的技巧有哪些

布置作业可不只是简单地给学生分配任务&#xff0c;而是需要运用一些技巧&#xff0c;以达到更好的教学效果。那么&#xff0c;老师应该如何布置作业呢&#xff1f; 一、作业要有针对性 布置作业时&#xff0c;老师应该根据学生的实际情况和课程要求&#xff0c;有针对性地设…

tinyxml2

使用tinyxml2&#xff0c;得知道一些xml基础 xml tutorial--菜鸟 tinyxml2类对象 链接 结构 XMLNode 什么是节点 节点&#xff1a;元素、声明、文本、注释等。 XMLDocument xml文档(文件)对象。 作用&#xff1a; 加载xml文件&#xff0c; tinyxml2作用 先定义两个宏 …

阿里云服务器地域如何选择?哪个地域价格优惠一些?

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…

【数据结构】堆的实现和排序

目录 1、堆的概念和结构 1.1、堆的概念 1.2、堆的性质 1.3、堆的逻辑结构和存储结构 2、堆的实现 2.1、堆的初始化和初始化 2.2、堆的插入和向上调整算法 2.3、堆的删除和向下调整算法 2.4、取堆顶的数据和数据个数 2.5、堆的判空和打印 2.6、测试 3、堆的应用 3.1…

CentOS查看修改时间

经常玩docker的朋友应该都知道&#xff0c;有很多的镜像运行起来后&#xff0c;发现容器里的系统时间不对&#xff0c;一般是晚被北京时间8个小时&#xff08;不一定&#xff09;。 这里合理怀疑是镜像给的初始时区是世界标准时间&#xff08;也叫协调世界时间&#xff09;。 有…

CPU密集型计算、IO密集型计算、多进程、多线程

参考链接&#xff1a; 使用多进程multiprocessing模块加速程序的运行_哔哩哔哩_bilibili 什么是CPU密集型计算、IO密集型计算&#xff1a; CPU密集型&#xff1a; CPU密集型也叫计算密集型&#xff0c;是指I/O在很短的时间就可以完成&#xff0c;CPU需要大量的计算和处理&a…

44.5K Star,简单易用自动化运维监控工具

Hi&#xff0c;骚年&#xff0c;我是大 G&#xff0c;公众号「GitHub指北」会推荐 GitHub 上有趣有用的项目&#xff0c;一分钟 get 一个优秀的开源项目&#xff0c;挖掘开源的价值&#xff0c;欢迎关注。 今天介绍一个开源的自动化运维监控工具&#xff0c;它是一个轻量的开源…

【征服redis1】基础数据类型详解和应用案例

博客计划 &#xff0c;我们从redis开始&#xff0c;主要是因为这一块内容的重要性不亚于数据库&#xff0c;但是很多人往往对redis的问题感到陌生&#xff0c;所以我们先来研究一下。 本篇&#xff0c;我们先看一下redis的基础数据类型详解和应用案例。 1.redis概述 以mysql为…

Linux编译器--gcc和g++使用

gcc和g使用 一、gcc/g的作用1.1 预处理1.2 编译1.3 汇编1.4 链接 二、静态库和动态库三、make/Makefile3.1 make/Makefile3.2 依赖关系和依赖方法3.3 多文件编译3.4 make原理3.5 项目清理 四、linux下的第一个小程序-进度条4.1 行缓冲区的概念4.2 \r和\n4.3 进度条代码 一、gcc…

Verilog刷题笔记15

题目&#xff1a; An adder-subtractor can be built from an adder by optionally negating one of the inputs, which is equivalent to inverting the input then adding 1. The net result is a circuit that can do two operations: (a b 0) and (a ~b 1). See Wikipe…

Java数据结构之图(头歌平台,详细注释)

第1关&#xff1a;图的表示 任务描述 图&#xff08;Graph&#xff09;是表示一些事物或者状态的关系的表达方法。由于许多问题都可以归约为图的问题&#xff0c;人们提出了许多和图相关的算法。 本关任务&#xff1a;学习图的相关概念和表示&#xff0c;并用邻接表示图。 相关…