iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >如何解决mysql深分页问题
  • 839
分享到

如何解决mysql深分页问题

2024-04-02 19:04:59 839人浏览 八月长安
摘要

今天小编给大家分享一下如何解决Mysql深分页问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一

今天小编给大家分享一下如何解决Mysql深分页问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

如何解决mysql深分页问题

日常需求开发过程中,相信大家对于limit一定不会陌生,但是使用limit时,当偏移量(offset)非常大时,会发现查询效率越来越慢。一开始limit 2000时,可能200ms,就能查询出需要的到数据,但是当limit 4000 offset 100000时,会发现它的查询效率已经需要1S左右,那要是更大的时候呢,只会越来越慢。

概括

本文将会讨论当mysql大数据量的情况,如何优化深分页问题,并附上最近的优化慢sql问题的案例伪代码。

1、limit深分页问题描述

先看看表结构(随便举了个例子,表结构不全,无用字段就不进行展示了)

CREATE TABLE `p2p_detail_record` (
  `id` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '主键',
  `batch_num` int NOT NULL DEFAULT '0' COMMENT '上报数量',
  `uptime` bigint NOT NULL DEFAULT '0' COMMENT '上报时间',
  `uuid` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '会议id',
  `start_time_stamp` bigint NOT NULL DEFAULT '0' COMMENT '开始时间',
  `answer_time_stamp` bigint NOT NULL DEFAULT '0' COMMENT '应答时间',
  `end_time_stamp` bigint NOT NULL DEFAULT '0' COMMENT '结束时间',
  `duration` int NOT NULL DEFAULT '0' COMMENT '持续时间',
  PRIMARY KEY (`id`),
  KEY `idx_uuid` (`uuid`),
  KEY `idx_start_time_stamp` (`start_time_stamp`) //索引,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='p2p通话记录详情表';

假设我们要查询的深分页SQL长这样

select * 
from p2p_detail_record ppdr 
where ppdr .start_time_stamp >1656666798000 
limit 0,2000

如何解决mysql深分页问题

查询效率是94ms,是不是很快?那如果我们limit 100000,2000呢,查询效率是1.5S,已经非常慢,那如果更多呢?

如何解决mysql深分页问题

2、sql慢原因分析

让我们来看看这条sql的执行计划

如何解决mysql深分页问题

也走到了索引,那为什么还是慢呢?我们先来回顾一下mysql 的相关知识点。

聚簇索引和非聚簇索引

聚簇索引: 叶子节点储存的是整行的数据。

非聚簇索引: 叶子节点储存的是整行的数据对应的主键值。

如何解决mysql深分页问题

使用非聚簇索引查询的流程

  • 通过非聚簇索引树,找到对应的叶子节点,获取到主键的值。

  • 再通过取到主键的值,回到聚簇索引树,找到对应的整行数据。(整个过程称为回表

回到这条sql为什么慢的问题上,原因如下

1、limit语句会先扫描offset+n行,然后再丢弃掉前offset行,返回后n行数据。也就是说limit 100000,10,就会扫描100010行,而limit 0,10,只扫描10行。这里需要回表100010次,大量的时间都在回表这个上面。

方案核心思路: 能不能事先知道要从哪个主键ID开始,减少回表的次数

常见解决方案

通过子查询优化

select * 
from p2p_detail_record ppdr 
where id >= (select id from p2p_detail_record ppdr2 where ppdr2 .start_time_stamp >1656666798000 limit 100000,1) 
limit 2000

相同的查询结果,也是10W条开始的第2000条,查询效率为200ms,是不是快了不少。

如何解决mysql深分页问题

标签记录法

标签记录法: 其实标记一下上次查询到哪一条了,下次再来查的时候,从该条开始往下扫描。类似书签的作用

select * from p2p_detail_record ppdr
where ppdr.id > 'bb9d67ee6eac4cab9909bad7c98f54d4'
order by id 
limit 2000

备注:bb9d67ee6eac4cab9909bad7c98f54d4是上次查询结果的最后一条ID

使用标签记录法,性能都会不错的,因为命中了id索引。但是这种方式有几个缺点

  • 1、只能连续页查询,不能跨页查询。

  • 2、需要一种类似连续自增的字段(可以使用orber by id的方式)。

方案对比

  • 使用通过子查询优化的方式

优点: 可跨页查询,想查哪一页的数据就查哪一页的数据。

缺点: 效率不如标签记录法原因: 比如需要查10W条数据后,第1000条,也需要先查询出非聚簇索引对应的10W1000条数据,在取第10W开始的ID,进行查询。

  • 使用 标签记录法 的方式

优点: 查询效率很稳定,非常快。

缺点:

  • 不跨页查询,

  • 需要一种类似连续自增的字段

关于第二点的说明: 该点一般都好解决,可使用任意不重复的字段进行排序即可。若使用可能重复的字段进行排序的字段,由于mysql对于相同值的字段排序是无序,导致如果正好在分页时,上下页中可能存在相同的数据。

实战案例

需求: 需要查询查询某一时间段的数据量,假设有几十万的数据量需要查询出来,进行某些操作。

需求分析 1、分批查询(分页查询),设计深分页问题,导致效率较慢。

CREATE TABLE `p2p_detail_record` (
  `id` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '主键',
  `batch_num` int NOT NULL DEFAULT '0' COMMENT '上报数量',
  `uptime` bigint NOT NULL DEFAULT '0' COMMENT '上报时间',
  `uuid` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '会议id',
  `start_time_stamp` bigint NOT NULL DEFAULT '0' COMMENT '开始时间',
  `answer_time_stamp` bigint NOT NULL DEFAULT '0' COMMENT '应答时间',
  `end_time_stamp` bigint NOT NULL DEFAULT '0' COMMENT '结束时间',
  `duration` int NOT NULL DEFAULT '0' COMMENT '持续时间',
  PRIMARY KEY (`id`),
  KEY `idx_uuid` (`uuid`),
  KEY `idx_start_time_stamp` (`start_time_stamp`) //索引,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='p2p通话记录详情表';

伪代码实现

//最小ID 
String  lastId = null; 
//一页的条数 
Integer pageSize = 2000; 
List<P2pRecordVo> list ;
do{   
   list = listP2pRecordByPage(lastId,pageSize);    //标签记录法,记录上次查询过的Id 
   lastId = list.get(list.size()-1).getId();       //获取上一次查询数据最后的ID,用于记录
   //对数据的操作逻辑
   XXXXX();
 }while(isNotEmpty(list));
   
<select id ="listP2pRecordByPage">  
   select * 
   from p2p_detail_record ppdr where 1=1
   <if test = "lastId != null">
   and ppdr.id > #{lastId}
   </if>
   order by id asc
   limit #{pageSize}
</select>

这里有个小优化点: 可能有的人会先对所有数据排序一遍,拿到最小ID,但是这样对所有数据排序,然后去min(id),耗时也蛮长的,其实第一次查询,可不带lastId进行查询,查询结果也是一样。速度更快。

以上就是“如何解决mysql深分页问题”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网数据库频道。

您可能感兴趣的文档:

--结束END--

本文标题: 如何解决mysql深分页问题

本文链接: https://www.lsjlt.com/news/73945.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • 如何解决mysql深分页问题
    今天小编给大家分享一下如何解决mysql深分页问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一...
    99+
    2022-10-19
  • MySql深分页问题解决
    目录1. 问题描述2. 问题分析3. 验证测试3.1 创建两个表3.2 创建两个函数3.3 编写存储过程3.4 编写存储过程3.5 创建索引3.6 验证测试4. 解决方案4.1 使用索引覆盖+子查询优化4.2 起始位置重...
    99+
    2023-02-03
    MySql深分页
  • 如何解决mysql深度分页问题
    目录mysql深度分页问题1.基本分页:耗时0.019秒2.深度分页:耗时10.236秒3.深度ID分页:耗时0.052秒4.两步走深度分页:耗时0.049秒+0.017秒5.一步走深度分页:耗时0.05秒6.集成Bea...
    99+
    2023-01-09
    mysql深度分页 深度分页 mysql分页
  • 快速解决mysql深分页问题
    目录背景概括1、limit深分页问题描述2、sql慢原因分析聚簇索引和非聚簇索引常见解决方案通过子查询优化标签记录法方案对比实战案例总结背景 日常需求开发过程中,相信大家对于limit一定不会陌生,但是使用limit时,...
    99+
    2022-07-13
    mysql深分页 mysql分页
  • MySQL深分页问题解决思路
    目录一、MySQL深分页问题1、limit 语法解读2、回表二、优化方案一、MySQL深分页问题 我们在日常开发中,查询数据量比较大的时候,后端基本都会通过前端,移动端传过来的页码,...
    99+
    2022-12-22
    MySQL深分页 MySQL深分页问题
  • MySQL深分页问题解决的实战记录
    目录前言limit深分页为什么会变慢?通过子查询优化回顾B+ 树结构把条件转移到主键索引树INNER JOIN 延迟关联标签记录法使用between...and...手把手实战案例一...
    99+
    2022-11-12
  • MySQL深分页问题原理与三种解决方案
    目录1 深分页问题1.1 创建表1.2 新增100万条数据1.3 深分页语句1.4 结果分析2 深分页优化方案2.1 方案一2.2 方案二2.2.1 优化语句2.2.2 执行计划2.2.3 结果分析2.3 方案三2.3....
    99+
    2023-05-05
    MySQL深分页 MySQL深分页问题 MySQL深分页问题解决
  • MySQL调优之SQL查询深度分页问题怎么解决
    这篇文章主要讲解了“MySQL调优之SQL查询深度分页问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL调优之SQL查询深度分页问题怎么解决”吧!一、问题引入例如当前存在一...
    99+
    2023-07-05
  • mysql limit分页过慢的问题如何解决
    本篇内容主要讲解“mysql limit分页过慢的问题如何解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“mysql limit分页过慢的问题如何解决”吧!1、使用表的覆盖索引加速分页查询。由...
    99+
    2023-06-20
  • pagehelper分页乱套问题如何解决
    本篇内容介绍了“pagehelper分页乱套问题如何解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用pagehelper遇到的坑说明现...
    99+
    2023-07-04
  • es分页跨页问题怎么解决
    在处理ES分页跨页问题时,可以使用以下方法解决: 使用scroll API:scroll API允许在多次请求中保持一个持久化的...
    99+
    2023-10-28
    es
  • 解决MybatisPlus SqlServer OFFSET 分页问题
    目录问题错误源码重现找资料解决问题 使用MybatisPlus 连接 SqlServer 数据库 ,在分页的时候发生了如下的报错,sql语句和报错如下: Cause: com.mic...
    99+
    2022-11-13
  • 深度学习——LSTM解决分类问题
    RNN基本介绍 概述 循环神经网络(Recurrent Neural Network,RNN)是一种深度学习模型,主要用于处理序列数据,如文本、语音、时间序列等具有时序关系的数据。 核心思想 RNN的...
    99+
    2023-09-08
    深度学习 lstm 分类
  • Java深入分析与解决Top-K问题
    目录题目解题方案方法一方法二方法三题目 求最小的K个数 设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。 解题方案 方法一 排序(冒泡/选择) 思路 1,冒泡排序...
    99+
    2022-11-13
  • 解决pageHelper分页失效以及如何配置问题
    目录pageHelper分页失效及配置问题原因解决方案PageHelper分页无效及报错第一种情况SQL报错第二种情况分页无效总结pageHelper分页失效及配置问题 我在使用pa...
    99+
    2023-05-14
    pageHelper分页失效 pageHelper分页配置 pageHelper分页
  • 如何解决mysql添加分区出错的问题
    这篇文章主要介绍如何解决mysql添加分区出错的问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!mysql添加分区出错,报“1503”错误的原因:每一个分区表中的公式中的列,必须在...
    99+
    2022-10-18
  • MySQL如何解决幻读问题
    目录前言一、什么是幻读?二、幻读有什么问题?(1)需要单独解决(2)间隙锁引发的并发度三、如何解决幻读?三、总结前言   我们知道MySQL在可重复读隔离级别下别的事物提交的内容,是看不到的。而可提交隔离级别下是可以...
    99+
    2022-05-22
    MySQL 幻读
  • 如何解决mysql乱码问题
    小编给大家分享一下如何解决mysql乱码问题,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!  mysql的字符集支持(character set support)有两个方面:字...
    99+
    2022-10-19
  • 如何解决mysql性能问题
    这篇文章主要为大家展示了“如何解决mysql性能问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何解决mysql性能问题”这篇文章吧。 最近项目使用mys...
    99+
    2022-10-19
  • Mysql如何解决死锁问题
    这篇文章主要为大家展示了“Mysql如何解决死锁问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Mysql如何解决死锁问题”这篇文章吧。 ...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作