mysql 大分页查询优化_Mysql骚操作:优化大分页查询

背景

020417350d50211295002ee408e1cdab.png

系统结构如上图。经过排查是因为系统B拉取数据时间太长导致的推送超时。

系统B拉取数据的方法是根据_tiemstamp(数据操作时间)分页查询系统A的接口,即:

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

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

分页查询的性能瓶颈

B+树简述

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

b4ad065dfdb402a4093a75833448d577.png

上图是一颗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();

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

0887b17da849c94618c6c68cedd2bce5.png

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

b79216075f3533c6ab9dbced73b4558f.png

7239deb424004f91648469f29711822d.png

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

解决方法

针对于limit,有很多优化的方法,比如前端加缓存、或者使用分页加载的方式展示数据。(大部分用户请求数据的初始开始都不会很大)。在我们的使用场景中,调大超时时间的阈值也是可以的。

但是回到问题本身,问题出现的原因就是分页语句随着初始位置的增加,会有性能问题,所以治本的办法,是对这个语句进行优化,有两个优化方法:

1 延迟关联法:

我们先查询出符合要求的主键(由于查询的字段有索引,该索引的叶子节点就是主键,通过索引覆盖我们可以省去一次回表操作。)

然后再通过主键索引查询数据,这就省去了遍历数据找初始位置数据的过程

f4542a792ba989fbc652994c806811bc.png

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

2 主键阈值法

如果你的主键是自增的,那么就可以通过条件推算出符合条件的主键最大值&最小值(这里也是通过索引覆盖省去了一次回表操作)

然后再根据阈值,取数据即可,同样省去了遍历数据找初始位置数据的过程

fe4fd5bc833767e08c97d0f62b213d63.png

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

最后

最后对文章做一下补充说明:

1.文中优化效果是仅凭借调用一次SQL的耗时给出的,并不科学,仅仅是为了让大家有一个直观的概念。

2.无论是延迟关联法,还是主键阈值法。思想都是一样的,先把符合条件的主键找到,然后通过主键去定位符合条件的数据,这里优化了2个点:1.通过索引覆盖避免了回表;2.通过主键直接定位数据的方法,省去了在数据集中查询初始位置的过程

3.优化的效果随数据量增加而增强。万级别的数据优化效果可能并不明显。

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

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

相关文章

python --动态类型

转自&#xff1a;http://www.cnblogs.com/vamei/archive/2012/07/10/2582795.html 动态类型(dynamic typing)是Python另一个重要的核心概念。我们之前说过&#xff0c;Python的变量(variable)不需要声明&#xff0c;而在赋值时&#xff0c;变量可以重新赋值为任意值。这些都与动…

mysql 判断等于空字符串_mysql 判断null 和 空字符串

1.在mysql中null 不能使用任何运算符与其他字段或者变量(函数、存储过程)进行运算。若使用运算数据就可能会有问题。2.对null 的判断&#xff1a;创建一个user表&#xff1a;id 主健 name 可以为空select * from user;insert into user values(33,null); ##创建一条name为空的…

JS组件系列——Bootstrap Table 表格行拖拽

JS组件系列——Bootstrap Table 表格行拖拽 原文:JS组件系列——Bootstrap Table 表格行拖拽前言&#xff1a;之前一直在研究DDD相关知识&#xff0c;好久没更新JS系列文章了。这两天做了一个简单的业务需求&#xff0c;觉得效果还可以&#xff0c;今天在这里分享给大家&#x…

mysql 值到99999后不增值了_MySQL必知必会3

创建和操纵表创建表输入CREATE TABLE customers(cust_id int NOT NULL AUTO_INCREMENT,cust_name char(50) NOT NULL ,cust_address char(50) NULL ,cust_city char(50) NULL ,cust_state char(5) NULL ,cust_zip char(10) NULL ,cust_country char(50) NULL ,cust_contact cha…

Linux install innotop

innotop是mysql监控工具 1&#xff0c;下载 weget http://nchc.dl.sourceforge.net/project/innotop/innotop/1.6.0/innotop-1.6.0.zip 2&#xff0c;安装依赖包 yum install perl-DBI perl-DBD-MySQL perl-TermReadKey perl -y 3,安装innotop perl Makefile.PL make make ins…

mysql udp服务器_netty学习:UDP服务器与Spring整合(2)

上一篇文章中&#xff0c;介绍了netty实现UDP服务器的栗子。本文将会对UDP服务器与spring boot整合起来&#xff0c;并使用RedisTemplate的操作类访问Redis和使用Spring DATA JPA链接MySQL数据库&#xff0c;其中会使用多线程、异步等知识。只公布了一个框架&#xff0c;需要的…

1-4 TCP/IP协议族

网络协议是在内核中实现的&#xff0c;socket是对tcp/ip协议的系统调用&#xff0c;提供以下两点功能&#xff1a; 1. 将应用撑血数据从用户缓冲区中复制到TCP/UDP内核发送缓冲区&#xff0c;以交付内核发送来的数据&#xff08;比如send&#xff09;&#xff0c;或者从内核TCP…

python将数据写入excel_【Python】将数据库中的数据查询出来自动写入excel文档

近期每天都要监控一个数据。第一个版本是这样的&#xff1a;每天新增一个文档来汇总这个数据。这样搞了几天之后&#xff0c;过了一个周末&#xff0c;过来突然发现数据变多了很多&#xff0c;这个时候要调整策略&#xff0c;直接一个文档汇总出要的数据就可以了。这样查了两天…

OC 继承

一、基本概念 程序的世界和人类的“对象”世界在思想上是没有设么区别的&#xff0c;富二代继承了父母&#xff0c;自然就拥有了父母拥有的所有资源&#xff0c;子类继承了父类同样就拥有了父类所有的方法和属性&#xff08;成员变量&#xff09;。 在这里动物是猫类和狗类的父…

吃西瓜 最大子矩阵 三维的。 rqnoj93

真的好苦逼&#xff0c;这道神题&#xff0c;交了几十次都是70分&#xff0c;剩下的都TLE了&#xff0c;崩溃。 没办法&#xff0c;只能这样了。在网上看了别人的算法&#xff0c;大概思想是把三维的先压成两维&#xff0c;再把二维的弄成一维&#xff0c;这样就很容易了。 首先…

mysql 两张表差集_mysql中两张表使用left join on 求差集详解

1.表结构mysql> select * from allStudents;-----------| id | name |-----------| 1 | ???? || 2 | ???? || 3 | ???| 4 | four |-----------4 rows in set (0.00 sec)mysql> select * from currentStudents;------------| id | name |------------| 1 | luo…

Android 高级UI设计笔记08:Android开发者常用的7款Android UI组件(转载)

Android开发是目前最热门的移动开发技术之一&#xff0c;随着开发者的不断努力和Android社区的进步&#xff0c;Android开发技术已经日趋成熟&#xff0c;当然&#xff0c;在Android开源社区中也涌现了很多不错的开源UI项目&#xff0c;它们可以帮助Android开发者更方便快捷地完…

centos linux怎么安装mysql_CentOS-Linux系统下安装MySQL

一、mysql的安装Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器。基于RPM包管理&#xff0c;能够从指定的服务器自动下载RPM包并且安装&#xff0c;可以自动处理依赖性关系&#xff0c;并且一次安装所有依赖的软件包&…

Operating System-进程/线程内部通信-临界区(Critical Regions)

上一篇文章讲述了进程之间的竞争条件&#xff1a;多个进程同时进入一个共享区域&#xff0c;导致了数据的不一致&#xff0c;本文主要介绍如何解决这个问题。 一、临界区介绍 解决这个问题就是阻止多个进程同时进入这个共享区域&#xff0c;换句话说&#xff0c;进程之间针对这…

centos命令行安装mysql_Centos下安装mysql 总结

一、MySQL安装二、MySQL的几个重要目录MySQL安装完成后不象SQL Server默认安装在一个目录&#xff0c;它的数据库文件、配置文件和命令文件分别在不同的目录&#xff0c;了解这些目录非常重要&#xff0c;尤其对于Linux的初学者&#xff0c;因为 Linux本身的目录结构就比较复杂…

乘法逆元模板

1.扩展欧几里得求逆元 typedef long long ll;//ax by gcd(a,b) //传入固定值a,b.放回 dgcd(a,b), x , y void extendgcd(ll a,ll b,ll &d,ll &x,ll &y) {if(b0){da;x1;y0;return;}extendgcd(b,a%b,d,y,x);y-x*(a/b); }//Ax1(mod M)&#xff0c;gcd(A,M)1 //输入&…

【html】【19】高级篇--大事件时间轴

下载:  http://sc.chinaz.com/jiaoben/131112181390.htm 其它:  http://sc.chinaz.com/tag_jiaoben/shijianzhou.html 效果:   html 代码: 1 <!DOCTYPE html>2 <html>3 <head>4 <meta http-equiv"Content-Type" content"text/html; …

必须声明标量变量_Excel VBA解读(136): 在用户定义函数中的变体、引用、数组、计算表达式、标量...

学习Excel技术&#xff0c;关注微信公众号&#xff1a;excelperfect在前面的几篇文章中&#xff0c;我们自定义的函数使用定义为Range的参数来从Excel工作表中获取数据&#xff0c;例如&#xff1a;Function VINTERPOLATEB(Lookup_Value As Variant, _Table_Array As Range, _C…

HTMl5的存储方式sessionStorage和localStorage详解

html5中的Web Storage包括了两种存储方式&#xff1a;sessionStorage和localStorage。sessionStorage用于本地存储一个会话&#xff08;session&#xff09;中的数据&#xff0c;这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁因此sessionStorage不是…

mysql5.7四字节中文_mysql 字节问题,中文和数字

在mysql 5.1.5-alpha下测试得出如下结论latin1:1character1byte, 1汉字2character,也就是说一个字段定义成 varchar(200)&#xff0c;则它可以存储100个汉字或者200个字母。这一点要注意&#xff0c;尤其是当字段内容是字母和汉字组成时&#xff0c;尽量假设字段内容都是由汉字…