mysql索引使增删变慢_mysql优化之索引篇

mysql,对it打工人,这个几乎是必备的技能之一。mysql可以解决我们平时工作中的大量的、有关增删查改的问题。所以想深入了解mysql,我觉得关键在于他的增删查改背后的算法,开搞。

面对增删查改等问题,直接通过场景来看吧

场景1

8bdb9fcf7e2f961b0d60acb81a434e39.png

有很多个数据,如上图右边的两个链表,顺序查找会会遍历每一个元素,会很慢,尤其是数据量很大的时候,遍历整个表都会会一次都会消耗大量的时间,而右边是一个二叉树,很明显可以看到,二叉树找到我们要的元素,最多只需要比对3次。常见的各种树的算法复杂度操作二叉查找树平衡二叉树红黑树

查找O(n)O(logn)Olog(n)

插入O(n)O(logn)Olog(n)

删除O(n)O(logn)Olog(n)

结论:链表不得行哦~

直接上二叉树吧

于是乎制作成二叉树,如下图右边的树。左边的链表89号元素需要遍历查找,而89的元素在在二叉树中,一次比对后就完成了定位。所以单一个二叉树就大大的优化了效率。

mysql有使用二叉树吗

没有!为什么呢?

想想一下这个一个场景:有一堆连续的数组,放到二叉树里边,那么他的二叉树结构就是一个链表的样子!说明了说在个别场景中,二叉树相对链表并没有优势可言。

ps:安利一个网站:https://www.cs.usfca.edu/~gal...

20b37205848f0c4b0132ab47e0dd981d.png

结论就是:二叉树也不见得很好,个别场景下它就是个链表

红黑树(二叉平衡树)

于是乎来到了红黑树,如下图。性质1:每个节点要么是黑色,要么是红色。

性质2:根节点是黑色。

性质3:每个叶子节点(NIL)是黑色。

性质4:每个红色结点的两个子结点一定都是黑色。

性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。

红黑树的应用比较广泛,主要是用它来存储有序的数据,它的时间复杂度是O(lgn),效率非常之高。TODO:

补充红黑树的伪算法

fedd1022226e151f51ae437431cf343e.png

这样看起来,红黑树效率会高一些,但是为什么mysql用的不是红黑树呢

因为实际场景的时候,数据量会很大,比如几百万的时候,树的层级可能达到20层,其实这个速度是很快了,但是依然不够高。在数据量大的时候,查找速度慢,它很难避免。

到这里可以得出,数据查询的效率,跟数据层级是有关系的

所以这里是不是可以思考一下:我们就让这个红黑树高度可控,控制在一个指定的深度,比如就三层,就会快很多?

这样子做得话,我们只能在一个节点上,挂载更多的节点,而不是只是两个。

实际上这就是b树

4381c123df0ab3625f5d6de5e3649357.png

看上去b树效果已经很好了,mysql有用到吗? NO!

实际上mysql用的是b+树

4c1d750e4e7cc109d06e7c4abadcfcf2.png

b树和b+树在底层存储数据的区别,叶子节点有一个指针指向左右,这样可以按照顺序地在叶子节点上遍历数据。在mysql中b+树的特点

mysql的b+树的第一层节点的大小是16kb。可以通过sql语句查询到:show global status liek "innodb_page_size"。其实第一层大索引大致可以存放(8+6)的数量是1170个的样子,第二层的节点也是1170个样样子。第三场就单纯存放索引,大概存放16个。

所以mysqlb+树的索引,大概可以存放的数据量在2000万个左右。

其实实际情况中,根节点的数据是常驻内存的,并不是每次查询都会重新载入一遍到内存。所以千万级别的表,查找依然很快。

实际上b+树的层级是可以大于3层的,需要的话可以设置。单实际上到这一步的时候,早就应该分库分表的。也就是为什么mysql不建议存储数据量大于2000万行左右数据的一个原因。

MyISAM和innodb的区别

tips:

myisam引擎mysql数据文件夹里边的文件简介:frm存放的是表结构,MYD是存放的数据,MYI存放的树索引。

那么myisam的数据内容,就是:

4d66c3b2fb526dd5737948c092c30dd4.png

当查找col1(假如col1是索引)等于30是,就是去myi的的文件里边找,按照左边的这个树形结构,定位到数据地址,拉出里边的索引位置。通过索引记录的位置,迅速定位到数据表的行的地址。这就是MYIsam

但实际中我们用的更多是innodb的引擎

为什么要用innodb呢?

1f0daf5095157a5da09ea47fc8117d36.png

innodb的文件结构。

5e500aec558e258d3a433a39f4cca01b.png

innodb在mysql数据库文件夹下的数据文件格式是:

frm代表表结构文件, idb存放的既包含数据,又包含索引。这几个名称猴嘴的mysql文件,相信做过数据迁移的童鞋,都不会觉得陌生,甚至看到他会有一丝丝气愤,当初就是这些让自己经常加班!

016370c0c0c0d2fe0addfb3e42d378f0.png

所以可以看出,innodb叶子节点上存放的不是索引,而直接是数据。Innodb的数据是直接挂在索引下的!

那么这些差异,导致不同引擎的数据库,都有哪些差异呢?

好几种索引介绍

聚集索引(聚蔟索引):innodb叶子节点包含了完整数据的索引。

非聚集索引(离散索引):myslam 叶子节点上,没有存放完整的数据。

为什么innodb表建议必须建主键,并且推荐使用整形的自增主键呢

uuid不合适,开篇死。因为uuid不是递增的

因为innodb的数据,必须有一个b+树的索引结构,来组织他的数据。mysql如果不建立主键,他就会进入这张表的第一列,判断如果这列数据每一个数据都是唯一的,那么就用这一列当做索引。如果遍历完了每一列,都没有唯一的列,那么mysql就会悄悄地为你建立一列隐藏列。这样一下走下来,就花费了太多运算了,所以推荐用户自建自增索引。

为什么建议自增整形呢?(雪花算法也是自增的。)因为查找的时候需要经常比对大小,每一层会逐个比对大小,用asii码去比对。而整形,在这一块比对的时候会快一些,所以要求整形。为甚自增呢?

为了快。

比如遇到范围查询的时候,定位到了一个元素,是不是就很快能判断上下位置的元素。

建立索引的时候可以选择btree,还有hash。hash是什么样的呢

hash定位速度很快哦。超级快!

9cbc97e77953fb7267e448d9f25cb384.png

首先算hash值,然后根据hash存放在某个位置,这个数据里边存放了值和节点的地址。当有多个的时候,就在这个后边直接添加。当数据量不大的时候,hash的效率非常高。

但实际上工作用绝大多数的时候都用的是b+而不是hash(99.99%都不是)。为什么呢?hash冲突,只是一个

最主要的是:不支持范围查询。当有返回查询的时候,就只能遍历查询。所以范围查询hash挂掉了,那么b+树就能hold住吗?

b+树的叶子节点有一个双向指针,来保持数据的连贯性。此外b+数据帮我们维护了一个从做到右的一种递增结构。所以范围查询,只要定位到了上限或者下限,直接顺藤摸瓜,很快就能完成定位。这也是为什么b+树叶子节点要维护一个双向指针的原因。

即使你没有按照顺序存放数据,b+树,也会帮你整理好顺序。比如7,8,6,也会将6放到78前。所以如果不是递增,调整顺序会消耗计算,尤其是在节点分裂的时候,要影响整个树的结构的时候,结构变化就会占用很多资源。但是如果顺序存放,反正结构性调整的概率是比较低的,相当于也是加快了存储的顺序。

这也是添加了索引为什么会让存储变慢的底层原因。

常见的联合索引的底层存储结构长什么样子的

292670a8dadef5e9c07c543ad442e576.png

从上图,可以看一下二级索引的特点,二级索引紧贴在一级索引后边,question:为什么二级索引长成这样,实际使用时运作机制是什么样的。

其实:索引是一种排好序的数据结构

想要理解多级索引的特点,其实,理解好mysql处理索引时,是如何为多级索引排序的就好了。

21d63dccafbffb35a2499f44883a6751.png

其实查找时,方法就是逐个比对。如果第一层,就已经可以比对处顺序了,那么这些数据,就直接就按这个顺序来排就行。如果第一个索引大小相同,那就根据第二个来排序,如果第二个相同,就看第三个。如果第三个也相同,就看主键,如果没有主键,那就看隐藏主键(所以建立自增索引很重要!)。

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

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

相关文章

POST、GET、@RequestBody和@RequestParam区别

RequestParam 注解RequestParam接收的参数是来自HTTP请求体或请求url的QueryString中。 RequestParam可以接受简单类型的属性,也可以接受对象类型。 RequestParam有三个配置参数: required 表示是否必须,默认为 true,必须。de…

python与linux关系_如何处理Linux / Python依赖关系?

由于缺乏对我想使用的一些库的支持,我将一些Python开发从Windows转移到Linux开发.我已经花了大部分时间搞乱了依赖关系.问题每当我拿起Linux,我通常会遇到一些依赖问题,通常是开发库,无论是通过apt-get,easy_install或pip安装.我可以浪费时间,应该是简单的任务,花更长的时间让图…

Springmvc接收json数据的4种方式

1、以RequestParam接收 前端传来的是json数据不多时:[id:id],可以直接用RequestParam来获取值 Autowired private AccomodationService accomodationService;RequestMapping(value "/update") ResponseBody public String updateAttr(RequestParam (&q…

centos安装mysql卡住_CentOS 6.4安装MySQL的过程中出现的bug

在CentOS 6.4下安装MySQL,下载一个源码包,感觉很简单,tar,./configure,make,make install 经典四步,弄这个也不是第一次了,但今天就是老出错,首先是./configure中&#x…

SpringMVC接受List的几种方式

说到SpringMVC接受List参数,可能有人会说这个是个坑!下面我来跟大家说怎么补这个坑。下面我分几种情况来讲: 一、只接收一个List 1、form表单提交 controller代码: ResponseBody RequestMapping("test") public voi…

mysql怎么加固_mysql安装及加固

mysql安装查看是否安装mysql我们先看一下有没有安装mysqlyum list installed mysql | grep mysql本地只安装了php链接mysql的库,没有安装mysql如果有安装,可以使用安装的或者卸载了重新安装添加yum源去mysql官网查找下面我就来安装下yum源sudo rpm -ivh …

python标准库os的方法listdir_使用python标准库快速修改文件名字

大家在追剧的时候会一次性下载很多电影,但是很烦人的是前面会有很多电影网站的广告前缀。今天我将介绍一个简短的代码,快速修改这些文件的名字。工具:os首先在电影目录下新建一个py文件,并导入osimport osos,是python中…

RabbitMQ保姆级教程

文章目录 前言一、MQ是什么? 1.1 AMQP 二、在Linux安装RabbitMQ 2.1 安装2.2 RabbitMQ启动命令2.3 开启RabbitMQ 后台管理界面 2.3.1 登录rabbitMQ UI界面 2.3 Docker启动RabbitMQ2.4 常见消息模型2.5 生产者(Producer) / 消费者(Consumer)2.6 工作队列模式(Work Q…

spring mysql 连接池配置_SpringBoot数据库连接池常用配置

关注公众号:程序猿王国 持续更新,每日分享在配置文件中添加配置如下(我使用的是多数据源):spring.datasource.primary.urljdbc\:mysql\://localhost\:3306/test?useUnicode\true&characterEncoding\utf-8spring.datasource.prim…

交换机到底是啥?

1、交换机 交换机个人资料: 1.证件照 注:copy 百度百科 我的博客/交换机到底是啥? 这东西乍一看有点像月光宝盒,是不是。 2.个人简介 交换机(Switch)意为“开关”是一种用于电(光&#xff0…

unity3d 动态合批设置_Unity3D SkinnedMeshRenderer合批优化

最近做了性能优化相关的工作,其中一些是关于战斗模块的渲染的。主要是对场景中使用的基于SkinnedMeshRenderer的网格进行了一些合批优化(降DC),记录如下。项目使用的Unity版本为5.6.4p1。游戏中的战斗模块是这样的:战斗逻辑由服务器承担&…

java——Final修饰成员变量的注意事项

一.Final 修饰成员变量的注意事项 final修饰成员变量,该成员变量必须在创建对象之前进行赋值,否则编译失败final修饰成员变量,固定的不是成员变量拥有的默认值,如果固定的是默认值,那么将导致被final修饰的…

php 编写mysql_php编写数据写入mysql问题

我刚写好的:前台是htm界面填写数据留言板...我刚写好的:前台是 htm界面 填写数据留言板你的姓名:你的性别:男 女你的email:你的留言内容:后台是:if(isset($_POST)) // 只有 $_POST 变量存在&…

java 代码 点到线段的最短距离

// 点到直线的最短距离的判断 点(x0,y0) 到由两点组成的线段(x1,y1) ,( x2,y2 )private double pointToLine(int x1, int y1, int x2, int y2, int x0,int y0) {double space 0;double a, b, c;a lineSpace(x1, y1, x2, y2);// …

isNotBlank()和isNotEmpty()的区别——java中,StringUtils类中的一些常用方法

java中,StringUtils类中的一些常用方法 boolean isBlank(String str) //判断某字符串是否为空或长度为0或由空白符(whitespace)构成 StringUtils.isBlank(null) true StringUtils.isBlank("") true StringUtils.isBlank(" ") true StringUt…

java类的加载顺序_java类加载先后顺序

这里讲的不是类加载机制,是类的加载先后顺序。话不多说了,先设定以下场景:package com.jingdong;public class A {public static void main(String[] args){System.out.println(Ib.b);B bnew B();b.ibTest();}}public class B implements Ib{private D d;private C …

MyBatis:模糊查询的4种实现方式

1、根据姓名模糊查询员工信息 1.1、方式一 步骤一:编写配置文件 步骤二:测试 步骤三:分析 此种方式需要在调用处手动的去添加“%”通配符。 1.2、方式二 说明: 使用方式一可以实现模糊查询,但是有一点不方便的地…

java 阻塞 socket_java socket非阻塞I/O

1 非阻塞(Nonblocking)体系结构在这一部分,我将从理论的角度来解释非阻塞体系的结构及其工作原理。这部“喜剧”(当然,如果你喜欢的话也可以称做戏剧)的“人物”如下:●服务器端:接收请求的应用程序。●客户端:向…

java panel frame_Java 版 (精华区)--Frame和Panel的区别【转载】

初学Java的时候一直弄不清Frame和Panel的区别,都是在上面装组件,也没看出什么所以然,一直稀里糊涂地用。最近看来一下Java类库中几个主要类的源文件,才明白了一点所以然。写下了此文,希望能给大家一点帮助。让我们先看…

js解析java对象数组_js接收并转化Java中的数组对象的方法

在做项目时,要向ocx控件下发命令,就要在js中得到java中的对象,然后拼成一种格式,下发下去。。。当对象是一个时比较简单,但如果对象是一个数组时,就略显麻烦了。开始我以为有简单的方式,可以直接…