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…

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 …

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类的加载顺序_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 mod函数的使用方法_java 数学计算的具体使用

java.lang.Math 库提供了常用的数学计算工具常量final double E 2.7182818284590452354; // 自然对数底数final double PI 3.14159265358979323846; // 圆周率final double DEGREES_TO_RADIANS 0.017453292519943295; // 角度转弧度final double RADIANS_TO_DEGREES 57.295…

java的debug模式_java第六章:debug模式介绍及大量实例练习

1.Debug模式1.1什么是Debug模式【理解】是供程序员使用的程序调试工具,它可以用于查看程序的执行流程,也可以用于追踪程序执行过程来调试程序。1.2Debug模式操作流程【应用】如何加断点选择要设置断点的代码行,在行号的区域后面单击鼠标左键即…

注解RequestMapping中的URI路径最前面到底需不需要加斜线?

注解RequestMapping中的URI路径最前面到底需不需要加斜线? 您有没有这样的困惑:在协同开发过程中,使用RequestMapping,或者是GetMapping,或者是PostMapping这类注解时,有的程序员加了斜线,有的程序员没有…

java ajax jquery分页插件_jquery ajax分页插件的简单实现

说到基于jQuery的ajax分页插件,那我们就先看看主要的代码结构:1、首先定义一个pager对象:var sjPager window.sjPager {opts: {//默认属性pageSize: 10,preText: "pre",nextText: "next",firstText: "First"…

java thrift连接池_由浅入深了解Thrift之客户端连接池化

一、问题描述在上一篇《由浅入深了解Thrift之服务模型和序列化机制》文章中,我们已经了解了thrift的基本架构和网络服务模型的优缺点。如今的互联网圈中,RPC服务化的思想如火如荼。我们又该如何将thrift服务化应用到我们的项目中哪?实现thrif…

Vue 进阶组件实战应用 -- 父子组件传值的应用实例(子父组件传值的两种触发方式)

基础的子组件和父组件通信已经搞定了,可以看此博客 父子组件传值基础应用 需求 现在需求是在一个父页面引用子组件,不只是要实现基本的父子组件传值。并且子组件给父组件传值的触发条件要在父页面触发。 目前小编采用的方式是使用ref 属性this.emit 方法…

学习Spring Boot:(一)入门

微服务 微服务其实是服务化思路的一种最佳实践方向,遵循SOA(面向服务的架构)的思路,各个企业在服务化治理上面的道路已经走得很远了,整个软件交付链上各个环节的基础设施逐渐成熟了,微服务就诞生了。 微服务…

学习Spring Boot:(二)启动原理

前言 主要了解前面的程序入口 SpringBootApplication 这个注解的结构。 正文 参考《SpringBoot揭秘 快速构建微服务体系》第三章的学习,总结下。 SpringBootApplication背后的秘密 Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented In…

学习Spring Boot:(四)应用日志

前言 应用日志是一个系统非常重要的一部分,后来不管是开发还是线上,日志都起到至关重要的作用。这次使用的是 Logback 日志框架。 正文 Spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持&#xff0c…