如题,年前做了一个需求,涉及到Mysql大分页查询,整理一下,希望对需要的小伙伴有帮助。

背景分页查询的性能瓶颈B+树简述B+比起二叉查找树,有什么优势?分页查询过程测试集解决方法1 延迟关联法:2 主键阈值法最后

背景


  系统结构如上图。经过排查是因为系统B拉取数据时间太长导致的推送超时。
  系统B拉取数据的方法是根据_tiemstamp(数据操作时间)分页查询系统A的接口,即:

1SELECT 字段名
2FROM 表名
3WHERE _timestamp >= beginTime AND _timestamp <= endTime 
4LIMIT n, m;

  由于该数据是从其他数据源中导入的,所以_timestamp这个字段值几乎相同,这就导致了在我们的查询范围内存在大约150万的数据。一般遇到这种情况,首先想到的就是是否需要给_timestamp添加索引,这张表上是存在_timestamp索引的。那么为什么还会出现这个问题呢?这就要从分页查询本身说起了。

分页查询的性能瓶颈

B+树简述

  首先我们要了解InnoDB存储引擎中的B+数索引。这里我简单总结一下:


  上图是一颗B+树,通过观察我们可以发现它的一些特点:
  1.每个节点中子节点个个数不能少于m/2个,不能大于m个(B+树是一颗m叉树,图中m=3)
  2.根节点的节点个数可以超过m/2个,这是一个例外
  上述两点特性是为了保证B+树的查询效率。
  节点数超过m越多,在总节点数相同的情况下,树的高度h就越小,此时m叉数就会向链表退化(O(logn)->O(n))。
  节点数小于m/2越多,在总节点数相同的情况下,树的高度h就越高,此时查询数据,就需要经历更多次的IO

  3.m叉树非叶子节点只存储索引,不存储数据
  4.通过链表将叶子节点串联在一起,这样可以方便按区间查找。

B+比起二叉查找树,有什么优势?

  更矮,这就减少了IO次数。
  由于非叶子节点不存储数据,上图查询任何数据,都需要3次IO,查询性能更稳定
  由于叶子节点使用了链表连接,范围查询更简便。

分页查询过程

  1.首先通过非主键索引查询出所有条件的主键
  2.通过主键索引,定位到数据
  3.不断重复上述操作
  4.根据分页条件,确定返回数据的启始位置以及数据量
  5.返回数据
  可以看出,初始位置值越大,定位时需要查询的数据就越多,查询效率也会越低

测试集

  为了测试优化效果,我准备了150万测试数据(需要跑几分钟)。

 1# 建表语句
2CREATE TABLE `test`(
3  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
4  `name` varchar(512) NOT NULL DEFAULT '无' COMMENT '创建人',
5  `_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
6  PRIMARY KEY (`id`),
7  KEY `ix_timestamp` (`_timestamp`)
8) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试表';
9
10
11# 通过存储过程导入数据
12drop procedure idata;
13delimiter ;;
14create procedure idata()
15begin
16  declare i int;
17  set i=1;
18  while(i<=1500000)do
19    insert into test values(i, i, now());
20    set i=i+1;
21  end while;
22end;;
23delimiter ;
24
25call idata();

  接着,我们看一下使用索引的情况下,分页查询语句的耗时情况。


  可以看出,在使用索引的情况下,无论初始位置是0,还是145万,Mysql都会扫描所有符合条件的数据,然后找到初始位置的数据,向后查偏移量个数据,最后返回。

  这两条语句的执行速度差距非常大,大约3个数量级(0.00sec,10 sec)

解决方法

  针对于limit,有很多优化的方法,比如前端加缓存、或者使用分页加载的方式展示数据。(大部分用户请求数据的初始开始都不会很大)。在我们的使用场景中,调大超时时间的阈值也是可以的。
  但是回到问题本身,问题出现的原因就是分页语句随着初始位置的增加,会有性能问题,所以治本的办法,是对这个语句进行优化,有两个优化方法:

1 延迟关联法:

  我们先查询出符合要求的主键(由于查询的字段有索引,该索引的叶子节点就是主键,通过索引覆盖我们可以省去一次回表操作。)
  然后再通过主键索引查询数据,这就省去了遍历数据找初始位置数据的过程


  通过延迟关联的方法,我们将10sec的耗时降低到了1.58sec,优化了将近1个数量级。

2 主键阈值法

  如果你的主键是自增的,那么就可以通过条件推算出符合条件的主键最大值&最小值(这里也是通过索引覆盖省去了一次回表操作)
  然后再根据阈值,取数据即可,同样省去了遍历数据找初始位置数据的过程


  通过主键阈值法的方法,我们将10sec的耗时降低到了1.12sec,优化了1个数量级

最后

  最后对文章做一下补充说明:
  1.文中优化效果是仅凭借调用一次SQL的耗时给出的,并不科学,仅仅是为了让大家有一个直观的概念。
  2.无论是延迟关联法,还是主键阈值法。思想都是一样的,先把符合条件的主键找到,然后通过主键去定位符合条件的数据,这里优化了2个点:1.通过索引覆盖避免了回表;2.通过主键直接定位数据的方法,省去了在数据集中查询初始位置的过程
  3.优化的效果随数据量增加而增强。万级别的数据优化效果可能并不明显。

  最后,期待您的订阅和点赞,专栏每周都会更新,希望可以和您一起进步,同时也期待您的批评与指正!

Mysql优化大分页查询的更多相关文章

  1. MySQL 如何优化大分页查询?

    一 背景 大部分开发和DBA同行都对分页查询非常非常了解,看帖子翻页需要分页查询,搜索商品也需要分页查询.那么问题来了,遇到上千万或者上亿的数据量怎么快速的拉取全量,比如大商家拉取每月千万级别的订单数 ...

  2. Mysql优化_慢查询开启说明及Mysql慢查询分析工具mysqldumpslow用法讲解

    Mysql优化_慢查询开启说明及Mysql慢查询分析工具mysqldumpslow用法讲解   Mysql慢查询开启 Mysql的查询讯日志是Mysql提供的一种日志记录,它用来记录在Mysql中响应 ...

  3. 分页查询信息(使用jdbc连接mysql数据库实现分页查询任务)

             分页查询信息       使用jdbc连接mysql数据库实现分页查询任务 通过mysql数据库提供的分页机制,实现商品信息的分页查询功能,将查询到的信息显示到jsp页面上. 本项目 ...

  4. 在MySQL中如何使用覆盖索引优化limit分页查询

    背景 今年3月份时候,线上发生一次大事故.公司主要后端服务器发生宕机,所有接口超时.宕机半小时后,又自动恢复正常.但是过了2小时,又再次发生宕机. 通过接口日志,发现MySQL数据库无法响应服务器.在 ...

  5. [转] MySql 优化 大数据优化

    一.我们可以且应该优化什么? 硬件 操作系统/软件库 SQL服务器(设置和查询) 应用编程接口(API) 应用程序 ------------------------------------------ ...

  6. mysql和oracle 分页查询(转)

    最近简单的对oracle,mysql,sqlserver2005的数据分页查询作了研究,把各自的查询的语句贴出来供大家学习..... (一). mysql的分页查询 mysql的分页查询是最简单的,借 ...

  7. mysql和oracle分页查询

    MYSQL分页查询 方式1: select * from table order by id limit m, n; 该语句的意思为,查询m+n条记录,去掉前m条,返回后n条记录.无疑该查询能够实现分 ...

  8. mysql优化:慢查询分析、索引配置优化

    一.优化概述二.查询与索引优化分析a.性能瓶颈定位show命令慢查询日志explain分析查询profiling分析查询b.索引及查询优化三.配置优化 max_connections back_log ...

  9. Mysql 优化,慢查询

    最近项目上遇到点问题,服务器出现连接超时.上次也是超时,问题定位到mongodb上,那次我修改好了,这次发现应该不是这个的问题了. 初步怀疑是mysql这边出问题了,写的sql没经过压力测试,导致用户 ...

随机推荐

  1. php--0与空的判断

    使用empty()函数判断,两者都是true $a=0; if(trim($a)=="") { echo '数字0'; }

  2. caffe之mac环境下通过XCode调试C++程序

    caffe log输出参考:http://blog.csdn.net/langb2014/article/details/50482150mac下用xcode开发caffe:http://coldmo ...

  3. JS的时间差换算(String to 自己想要的时间格式)

    JS的时间差换算(String to 标准的时间格式) 1.字符串到标准时间格式: 字符串: var time1="2018-05-11 00:00:00" var time2=& ...

  4. 吴裕雄--天生自然 R语言开发学习:回归

    #------------------------------------------------------------# # R in Action (2nd ed): Chapter 8 # # ...

  5. EROS安装(windows)

    版本查看 基础环境安装 npm i eros-cli -g

  6. html常用事件

    1.onblur 当窗口失去焦点时运行 2.click 点击鼠标触发的事件 3.onfocus 当窗口获得焦点时运行 4.oninput 当元素获得用户输入时运行 5.onsubmit 当提交表单时运 ...

  7. 测试工程师不懂AI,还有未来吗?

    阿里妹导读:近几年人工智能.机器学习等词漫天遍地,似乎有一种无AI,无研发,无AI,无测试的感觉.有人说:不带上"智能"二字,都不好意思说自己是创新.我们先暂且不评论对错,只探讨这 ...

  8. AQS总结

    前言 AQS(Abstract Queued Synchronizer)是JUC并发包中的核心基础组件,作者是大名鼎鼎的Doug Lea.通过AQS可以实现大部分的同步需求. 宏观架构 AQS包括一个 ...

  9. 分析Android中View的工作流程

    在分析View的工作流程时,需要先分析一个很重要的类,MeasureSpec.这个类在View的测量(Measure)过程中会用到. MeasureSpec MeasureSpec是View的静态内部 ...

  10. PM2.5如何引发心脏病的?

    过去的几十年里,科学家们一点一滴地积累起关于空气污染如何威胁人类健康的新认识.他们的注意力大多集中在肺部疾病,包括癌症上面.对空气污染具体危害的认识越来越多,但是对污染的控制和治理却显得举步维艰.面对 ...