我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MySQL深度分页

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MySQL深度分页

1. 什么是深度分页

深度分页问题的本质是在 MySQL 数据库中,通过 LIMIT 和 OFFSET 关键字进行分页时,MySQL 需要在每次查询时扫描整张表,直到找到当前页的数据。这种查询方式需要进行大量的磁盘 I/O 和内存操作,导致查询效率非常低下。当我们每次查询的记录数很小,但是查询次数很多时,就会产生大量的 I/O 操作,严重影响查询效率。
例如有个sql

select id,name,balance from account where update_time> '2020-09-19' limit 100000,10;

假设update_time 是有索引的,这个sql的执行流程:

  1. 通过普通二级索引树idx_update_time,过滤update_time条件,找到满足条件的记录ID。
  2. 通过ID,回到主键索引树,找到满足记录的行,然后取出展示的列(回表)
  3. 扫描满足条件的100010行,然后扔掉前100000行,返回。

假如 LIMIT 和 OFFSET 关键字同时进行使用的话,limit语句会先扫描offset+n行,然后再丢弃掉前offset行,返回后n行数据。也就是说limit 100000,10,就会扫描100010行,而limit 0,10,只扫描10行。这就是深度分页问题。

2. 优化方式

1. 通过子查询优化

因为以上的SQL,回表了100010次,实际上,我们只需要10条数据,也就是我们只需要10次回表其实就够了。因此,我们可以通过减少回表次数来优化。
其实我们只需要把条件转移到主键索引树就行了。

如果我们把查询条件,转移回到主键索引树,就可以减少回表次数了。转移到主键索引树查询的话,查询条件得改为主键id了,之前SQL的update_time这些条件就抽到子查询。
子查询那里怎么抽的呢?因为二级索引叶子节点是有主键ID的,所以我们直接根据update_time来查主键ID即可,同时我们把 limit 100000的条件,也转移到子查询,完整SQL如下:

select id,name,balance FROM account where id >= (select a.id from account a where a.update_time >= '2020-09-19' limit 100000, 1) LIMIT 10;

我们来看下执行计划
在这里插入图片描述

由执行计划得知,子查询 table a查询是用到了idx_update_time索引。首先在索引上拿到了聚集索引的主键ID,省去了回表操作,然后第二查询直接根据第一个查询的 ID往后再去查10个就可以了

2. 标签记录法

limit 深分页问题的本质原因就是:偏移量(offset)越大,mysql就会扫描越多的行,然后再抛弃掉。这样就导致查询性能的下降。
其实我们可以采用标签记录法,就是标记一下上次查询到哪一条了,下次再来查的时候,从该条开始往下扫描。就好像看书一样,上次看到哪里了,你就折叠一下或者夹个书签,下次来看的时候,直接就翻到了。
假设上一次记录到100000,则SQL可以修改为:

select  id,name,balance FROM account where id > 100000 order by id limit 10;

这样的话,后面无论翻多少页,性能都会不错的,因为命中了id索引。

3. 使用标签记录法的例子

假设现在有表结构如下,并且有200万数据

CREATE TABLE account ( id varchar(32) COLLATE utf8_bin NOT NULL COMMENT '主键', account_no varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '账号' amount decimal(20,2) DEFAULT NULL COMMENT '金额' type varchar(10) COLLATE utf8_bin DEFAULT NULL COMMENT '类型A,B' create_time datetime DEFAULT NULL COMMENT '创建时间', update_time datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (id), KEY `idx_account_no` (account_no), KEY `idx_create_time` (create_time) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='账户表' 

需求是这样:获取最2021年的A类型账户数据,上报到大数据平台。
我们来使用标签记录法,避免深度分页问题:

//查询最小IDString  lastId = accountDAO.queryMinId();//查询最小ID对应的SQL<select id="queryMinId" returnType=java.lang.String>select MIN(id) from accountwhere create_time >='2021-01-01 00:00:00'and type ='A'</select>//一页的条数Integer pageSize = 100;List<AcctountPO> list ;do{   list = listAccountByPage(lastId,pageSize);   //标签记录法,记录上次查询过的Id   lastId = list.get(list,size()-1).getId();    //上报大数据    postBigData(list);}while(CollectionUtils.isNotEmpty(list));<select id ="listAccountByPage">  select *   from account   where create_time >='2021-01-01 00:00:00'  and id > #{lastId}  and type ='A'  order by id asc    limit #{pageSize}</select>

其中使用order by id 是为了应对id主键不连续的情况。

B+树的节点数据是有大小顺序的,所以limit 10,能保证读到db中10条逻辑大小相邻的数据,即不会漏掉数据

来源地址:https://blog.csdn.net/qq_21040559/article/details/130555007

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MySQL深度分页

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何解决mysql深度分页问题

目录mysql深度分页问题1.基本分页:耗时0.019秒2.深度分页:耗时10.236秒3.深度ID分页:耗时0.052秒4.两步走深度分页:耗时0.049秒+0.017秒5.一步走深度分页:耗时0.05秒6.集成BeanSearcher框
2023-01-09

Mysql深度分页搜索怎么优化

要优化MySQL深度分页搜索,可以考虑以下几种方法:使用索引:确保搜索的字段上有适当的索引。对于深度分页搜索,较大的表可能需要创建复合索引,以提高查询性能。限制返回的列:只选择需要的列,而不是返回整行数据。这可以减少数据传输量,提高查询速度
Mysql深度分页搜索怎么优化
2023-10-28

MySQL深度分页(千万级数据量如何快速分页)

目录前言案例优化小结前言 后端开发中为了防止一次性加载太多数据导致内存、磁盘IO都开销过大,经常需要分页展示,这个时候就需要用到MySQL的LIMIT关键字。但你以为LIMIT分页就万事大吉了么,Too young,too simple啊,
2022-05-20

ElasticSearch 深度分页示例解析

这篇文章主要为大家介绍了ElasticSearch 深度分页示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-22

ElasticSearch深度分页怎么实现

本篇内容介绍了“ElasticSearch深度分页怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 前言ElasticSearch
2023-07-05

MySQL百万数据深度分页优化思路解析

目录业务场景瓶颈再现问题分析回表覆盖索引IOLIMTI 2000,10 ?问题总结解决方案优化前后性能对比业务场景一般在项目开发中会有很多的统计数据需要进行编程上报分析,一般在分析过后会在后台展示出来给运营和javascript产品进行分
2023-05-12

MySql深分页问题解决

目录1. 问题描述2. 问题分析3. 验证测试3.1 创建两个表3.2 创建两个函数3.3 编写存储过程3.4 编写存储过程3.5 创建索引3.6 验证测试4. 解决方案4.1 使用索引覆盖+子查询优化4.2 起始位置重定义4.3 降级策略
2023-02-03

MySQL快速创建800w条测试数据表&深度分页

MySQL快速创建800w条测试数据表&深度分页  汴水流,泗水流,流到瓜州古渡头。  吴山点点愁。    思悠悠,恨悠悠,恨到归时方始休。      月明人倚楼。 一、数据插入思路如果一条一条插入普通表的话,效率太低下,但内存表插入速度是很快的,可以先建立一
MySQL快速创建800w条测试数据表&深度分页
2021-11-01

MySQL调优之SQL查询深度分页问题怎么解决

这篇文章主要讲解了“MySQL调优之SQL查询深度分页问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL调优之SQL查询深度分页问题怎么解决”吧!一、问题引入例如当前存在一
2023-07-05

MySQL深分页问题解决思路

这篇文章主要介绍了优雅地解决mysql深分页问题,本文将会讨论当mysql表大数据量的情况,如何优化深分页问题,并附上最近的优化慢sql问题的案例伪代码,需要的朋友可以参考下
2022-12-22

快速解决mysql深分页问题

目录背景概括1、limit深分页问题描述2、sql慢原因分析聚簇索引和非聚簇索引常见解决方案通过子查询优化标签记录法方案对比实战案例总结背景日常需求开发过程中,相信大家对于limit一定不会陌生,但是使用limit时,当偏移量(offse
2022-07-13

MySQL深分页,limit 100000,10优化方式

目录一、limit深分页为什么会变慢二、优化方案2.1 通过子查询优化(覆盖索引)回顾B+树结构覆盖索引把条件转移到主键索引树2.2 INNER JOIN 延迟关联2.3 标签记录法(要求id是有序的)2.4 使用between&helli
MySQL深分页,limit 100000,10优化方式
2024-10-11

深度系统安装mysql

# 安装 Mysql 8.0.19下载 MySQL Community Server 8.0.19 【Compressed TAR Archive】(mysql-8.0.19-linux-glibc2.12-x86_64.tar.xz)1) 解压并移动(注意不
深度系统安装mysql
2019-04-15

MySQL深分页问题的原因及解决方案

目录前言第一部分:深分页问题的背景和影响什么是深分页?深分页的影响实际场景中的问题第二部分:mysql 索引结构和查询执行流程MySQL 索引概述查询执行流程深分页查询的问题案例分析第三部分:深分页性能下降的原因1. 索引扫描的局限性2.
MySQL深分页问题的原因及解决方案
2024-09-29

编程热搜

目录