mysql精讲_Mysql 索引精讲

开门见山,直接上图,下面的思维导图即是现在要讲的内容,可以先有个印象~

format,png

常见索引类型(实现层面)

索引种类(应用层面)

聚簇索引与非聚簇索引

覆盖索引

最佳索引使用策略

1.常见索引类型(实现层面)

首先不谈Mysql怎么实现索引的,先马后炮一下,如果让我们来设计数据库的索引,该怎么设计?

我们首先思考一下索引到底想达到什么效果?其实就是想能够实现快速查找数据的策略,所以索引的实现本质上就是一个查找算法。

但是跟普通的查找有所不同,因为我们的数据有一下特征:

1.存储的数据是非常非常多的

2.并且还不断的动态变化

所以实现索引时需要考虑到这两个特点。我们需要找一个最合适的数据结构算法来实现查找功能。

下面一起看下常见的查找策略,如下图:

format,png

由于前面说的两个特点我们首先排除静态查找的算法。

至于查找树,我们有二叉树和多叉树两种选择:

二叉树:如果选择二叉树的话,由于我们的数据量庞大,二叉树的深度会变得非常大,我们的索引树会变成参天大树,每次查询会导致很多磁盘IO。

多叉树:多叉树解决了了树的深度大的问题,那么我们到底选择B树还是B+树呢?

format,png

format,png

从上面图可知B+树的叶子节点存放了所有的索引值,并且叶子结点之间以链表的形式相互关联,所以我们只需从最左的链表遍历的话即可查找所有的值,最常见的用途就是范围查找,而B树则不满足这范围查找,又或者说实现特别复杂,所以Mysql最终选择了使用B+树实现这一功能。

1.1 B-Tree 索引(B+树)

先说明一下,虽然叫在Mysql官方叫做B-Tree索引,但采用的是B+树数据结构。

B-tree索引能够加快访问数据的速度,不需要进行全表扫描,而是从索引树的根节点层层往下搜索,在根节点存放了索引值和指向下一个节点的指针。

下面看下单列索引的数据怎么组织的。

create table User(

`name` varchar(50) not null,

`uid` int(4) not null,

`gender` int(2) not null,

key(`uid`)

);

复制代码

上面User 表给uid列创建了一个索引,那么往表里插入uid(96~102)的时候存储引擎是怎么管理索引的呢?看下面的索引树

format,png

1.在叶子节点存放所有的索引值,非叶子节点值是为了更快定位包含目标值的叶子节点

2.叶子节点的值是有序的

3.叶子节点之间以链表形式关联

下面在看一下多列(联合)索引的数据怎么组织的。

create table User(

`name` varchar(50) not null,

`uid` int(4) not null,

`gender` int(2) not null,

key(`uid`,`name`)

);

复制代码

给User 表创建了联合索引 key(uid,name) 这种情况下他的索引树是如下图所示。

format,png

特点跟单列索引一样,不同之处在于他的排序,如果第一个字段相同时会按第二个索引字段排序

如何通过B-tree快速查找数据?

format,png

对于InnoDb 存储引擎的B-tree索引,会按一下步骤通过索引找到行数据

如果使用了聚簇索引(主键),则叶子节点上就包含行数据,可直接返回

如果使用了非聚簇索引(普通索引),则在叶子节点存了主键,再根据主键查询一次上面 的聚簇索引,最后返回数据

对于MyISAM 存储引擎的B-tree索引,会按一下步骤通过索引找到行数据

在MyISAM 的索引树的叶子节点上除了索引值之外即没存储主键,也没存储行数据,而是存了指向行数据的指针,根据这个指针在从表文件查询数据。

1.2 Hash 索引(哈希表)

哈希索引是基于哈希表来实现的,只有精确匹配所有的所有列才能生效。

也就是说假设有个hash索引 key (col1,col2) 那么每次只有 col1和col2两个字段都用才能够生效。因为生成hash索引的时候是根据一个hash函数对所有的索引列取hash值来实现的。

如下方图,有个hash索引key(name)

format,png

当我们执行 mysql> select * from User where name='张三'; 时怎么利用hash索引快速查找的?

第一步,计算出hash值,hash(张三) = 1287

第二步,定位行号,比如key=1287 对应的行号为3

第三步,找到指定行并且比较name列值是否为张三做个校验

format,png

2.常见索引种类(应用层面)

主键索引

create table User(

`name` varchar(50) not null,

`uid` int(4) not null,

`gender` int(2) not null,

primary key(`uid`)

);

复制代码

主键索引是唯一的,通常以表的ID设置为主键索引,一个表只能有一个主键索引,这是他跟唯一索引的区别。

唯一索引

create table User(

`name` varchar(50) not null,

`uid` int(4) not null,

`gender` int(2) not null,

unique key(`name`)

);

复制代码

唯一索引主要用于业务上的唯一约束,他跟主键索引的区别是,一个表可以有多个唯一索引

单列索引

create table User(

`name` varchar(50) not null,

`uid` int(4) not null,

`gender` int(2) not null,

key(`name`)

);

复制代码

以某一个字段为索引

联合索引

create table User(

`name` varchar(50) not null,

`uid` int(4) not null,

`gender` int(2) not null,

key(`name`,`uid`)

);

复制代码

两个或两个以上字段联合组成一个索引。使用时需要注意满足最左匹配原则!

还有其他不常用的就不介绍了~

3.聚簇索引与非聚簇索引

什么是聚簇索引?

聚簇索引指的是他的 索引和行数据 在一起存储。也就是在一颗B+树的叶子结点上存储的不仅是他的索引值,还有对应的某一行的数据。待会儿看图便知。

聚簇索引不是一种索引,而是一种数据存储组织方式 !!!

crreate table test(

col1 int not null,

col2 int not null,

PRIMARY KEY(col1),

KEY(col2)

);

复制代码

如上所示,表test 由两个索引,分别是主键 col1 和 普通索引 col2。那么这俩索引跟聚簇非聚簇有啥关系呢?

会生成一个聚簇索引和一个非聚簇索引(二级索引),也就是说会组织两个索引树。主键索引会生成聚簇索引的树 以及以col2为索引的非聚簇索引的树。

InnoDb 将通过主键来实现聚簇索引 ,如果没有主键则会选选一个唯一非空索引来实现。如果没有唯一非空索引则会隐式生成一个主键。

下面看下聚簇索引和非聚簇索引在索引树上数据是怎么分布的,图片摘自《高性能Nysql》

下图是聚簇索引的数据组织方式。 col1为主键索引的聚簇索引树

索引列是主键 col1

format,png可以看出叶子结点除了存储索引值 列col1 (3~99~4700)值 之外还存储了其他列的值,如列col2 (92~8~13),如果还有别的列的话也会存储,或者换句话说聚簇索引树 在叶子节点上存储某个索引值对应的一行数据。

下图是非聚簇索引(二级索引)的数据组织方式。

索引列是 col2

format,png

与聚簇索引不同的是非聚簇索引在索引树叶子节点上除了索引值之外只存了主键值。而聚簇索引则存了一行数据。

假如有一条sql 语句 select * from test where col2=93;

上面这条语句会经历两次从索引树查找过程

1.第一步从非聚簇索引的索引树上找到包含col2=93的叶子节点,并定位到行的主键 3

2.第二步 根据主键 3 在从聚簇索引定位包含 主键=3的叶子节点并返回全部行数据。

以上说的都是基于InnoDb存储引擎的,MyISAM是不支持聚簇索引的,因为他的数据文件和索引文件是相互独立存储的 MyISAM存储引擎的索引树的叶子节点不会寸主键值,而存一个指向对应行的地址或者说是指针,然后再从表数据文件里去找,如下面图所示。

format,png

结论:

聚簇索引:

通常由主键或者非空唯一索引实现的,叶子节点存储了一整行数据

非聚簇索引:

又称二级索引,就是我们常用的普通索引,叶子节点存了索引值和主键值,在根据主键从聚簇索引查

4.覆盖索引

覆盖索引就是指索引包含了所有需要查询的字段。

create table User(

`name` varchar(50) not null,

`uid` int(4) not null,

`gender` int(2) not null,

key(`uid`,`name`)

);

复制代码

假如表 User有三个字段 User (name,uid,gender),且有个联合索引 key(name,uid)那么 执行如下面这条sql查询时就用到了 覆盖索引。

select name,uid from User where name in ('a','b') and uid >= 98 and uid <=100 ;

上面这条sql语句使用了联合索引 key(name,uid),并且只需查找 name,uid两个字段,所以使用了覆盖索引。覆盖索引有什么好处呢?先看一下下面这个图

format,png

上面这个图就是 联合索引key(name,uid) 所对应的索引树,从图中可以看出,如果我们只需查询(name,uid)两个字段的话,从索引树就能得到我们需要查的数据。不需要找到索引值之后再从表数据文件定位对应的行数据了。

覆盖索引好处

1.避免了对主键索引(聚簇)的二次查询

2.由于不需要回表查询(从表数据文件)所以大大提升了Mysql缓存的负载

总之大大提升了读取数据的性能

5.最佳索引使用策略

最后在讲讲使用索引过程中的避坑指南

独立的列

独立的列不是指单列索引,而是指索引列不能是表达式的一部分或者是函数的一部分。

select * FROM test where col1 + 1 =100; // 不能是表达式一部分

select * FROM test where ABS(col1) =100; // 不能是函数一部分

最左匹配原则

假如有个联合索引 key (col1,col2)。那么以下查询是索引无效的

select * from test where col2 = 3;

select * from test where col1 like '%3';

对于最左匹配原则,大家想一下B+树的叶子节点的关联就差不多知道为啥需要最左匹配原则了,因为B+的叶子结点,从左到右以链表的形式关联的,索引我们查询的时候要么范围查询,要么有明确的左边一个开始的索引值,不能跳过或者不明确如 like '%XYZ'这种查询。

索引值不能是null值

单列索引有null值会导致索引无效

多列索引只要有个列有null值会导致索引无效

使用聚簇索引和覆盖索引大大提升读取性能

因为聚簇索引和覆盖索引的索引树上就有了需要的字段,所以不需要回表文件查询,所以提升了查询速度

使用短索引

如果很长的字符串进行查询,只需匹配一个前缀长度,这样能够节省大量索引空间

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

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

相关文章

RT-Smart 官方 ARM 32 平台 musl gcc 工具链下载

前言 RT-Smart 的开发离不开 musl gcc 工具链&#xff0c;用于编译 RT-Smart 内核与用户态应用程序 RT-Smart musl gcc 工具链代码当前未开源&#xff0c;但可以下载到 RT-Thread 官方编译好的最新的 musl gcc 工具链 ARM 32位 平台 比如 RT-Smart 最好用的 ARM32 位 qemu 平…

OpenAI Whisper论文笔记

OpenAI Whisper论文笔记 OpenAI 收集了 68 万小时的有标签的语音数据&#xff0c;通过多任务、多语言的方式训练了一个 seq2seq &#xff08;语音到文本&#xff09;的 Transformer 模型&#xff0c;自动语音识别&#xff08;ASR&#xff09;能力达到商用水准。本文为李沐老师…

【经典简读】知识蒸馏(Knowledge Distillation) 经典之作

【经典简读】知识蒸馏(Knowledge Distillation) 经典之作 转自&#xff1a;【经典简读】知识蒸馏(Knowledge Distillation) 经典之作 作者&#xff1a;潘小小 知识蒸馏是一种模型压缩方法&#xff0c;是一种基于“教师-学生网络思想”的训练方法&#xff0c;由于其简单&#xf…

深度学习三大谜团:集成、知识蒸馏和自蒸馏

深度学习三大谜团&#xff1a;集成、知识蒸馏和自蒸馏 转自&#xff1a;https://mp.weixin.qq.com/s/DdgjJ-j6jHHleGtq8DlNSA 原文&#xff08;英&#xff09;&#xff1a;https://www.microsoft.com/en-us/research/blog/three-mysteries-in-deep-learning-ensemble-knowledge…

在墙上找垂直线_墙上如何快速找水平线

在装修房子的时候&#xff0c;墙面的面积一般都很大&#xff0c;所以在施工的时候要找准水平线很重要&#xff0c;那么一般施工人员是如何在墙上快速找水平线的呢&#xff1f;今天小编就来告诉大家几种找水平线的方法。一、如何快速找水平线1、用一根透明的软管&#xff0c;长度…

Vision Transformer(ViT)PyTorch代码全解析(附图解)

Vision Transformer&#xff08;ViT&#xff09;PyTorch代码全解析 最近CV领域的Vision Transformer将在NLP领域的Transormer结果借鉴过来&#xff0c;屠杀了各大CV榜单。本文将根据最原始的Vision Transformer论文&#xff0c;及其PyTorch实现&#xff0c;将整个ViT的代码做一…

Linux下的ELF文件、链接、加载与库(含大量图文解析及例程)

Linux下的ELF文件、链接、加载与库 链接是将将各种代码和数据片段收集并组合为一个单一文件的过程&#xff0c;这个文件可以被加载到内存并执行。链接可以执行与编译时&#xff0c;也就是在源代码被翻译成机器代码时&#xff1b;也可以执行于加载时&#xff0c;也就是被加载器加…

java 按钮 监听_Button的四种监听方式

Button按钮设置点击的四种监听方式注&#xff1a;加粗放大的都是改变的代码1.使用匿名内部类的形式进行设置使用匿名内部类的形式&#xff0c;直接将需要设置的onClickListener接口对象初始化&#xff0c;内部的onClick方法会在按钮被点击的时候执行第一个活动的java代码&#…

linux查看java虚拟机内存_深入理解java虚拟机(linux与jvm内存关系)

本文转载自美团技术团队发表的同名文章https://tech.meituan.com/linux-jvm-memory.html一, linux与进程内存模型要理解jvm最重要的一点是要知道jvm只是linux的一个进程,把jvm的视野放大,就能很好的理解JVM细分的一些概念下图给出了硬件系统进程三个层面内存之间的关系.从硬件上…

java function void_Java8中你可能不知道的一些地方之函数式接口实战

什么时候可以使用 Lambda&#xff1f;通常 Lambda 表达式是用在函数式接口上使用的。从 Java8 开始引入了函数式接口&#xff0c;其说明比较简单&#xff1a;函数式接口(Functional Interface)就是一个有且仅有一个抽象方法&#xff0c;但是可以有多个非抽象方法的接口。 java8…

java jvm内存地址_JVM--Java内存区域

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域&#xff0c;如图&#xff1a;1.程序计数器可以看作是当前线程所执行的字节码的行号指示器&#xff0c;通俗的讲就是用来指示执行哪条指令的。为了线程切换后能恢复到正确的执行位置Java多线程是…

java情人节_情人节写给女朋友Java Swing代码程序

马上又要到情人节了&#xff0c;再不解风情的人也得向女友表示表示。作为一个程序员&#xff0c;示爱的时候自然也要用我们自己的方式。这里给大家上传一段我在今年情人节的时候写给女朋友的一段简单的Java Swing代码&#xff0c;主要定义了一个对话框&#xff0c;让女友选择是…

java web filter链_filter过滤链:Filter链是如何构建的?

在一个Web应用程序中可以注册多个Filter程序&#xff0c;每个Filter程序都可以针对某一个URL进行拦截。如果多个Filter程序都对同一个URL进行拦截&#xff0c;那么这些Filter就会组成一个Filter链(也叫过滤器链)。Filter链用FilterChain对象来表示&#xff0c;FilterChain对象中…

java final static_Java基础之final、static关键字

一、前言关于这两个关键字&#xff0c;应该是在开发工作中比较常见的&#xff0c;使用频率上来说也比较高。接口中、常量、静态方法等等。但是&#xff0c;使用频繁却不代表一定是能够清晰明白的了解&#xff0c;能说出个子丑演卯来。下面&#xff0c;对这两个关键字的常见用法…

java语言错误的是解释运行的_Java基础知识测试__A卷_答案

考试宣言:同学们, 考试考多少分不是我们的目的! 排在班级多少的名次也不是我们的初衷!我的考试的目的是要通过考试中的题目,检查大家在这段时间的学习中,是否已经把需要掌握的知识掌握住了,如果哪道题目你不会做,又或者做错了, 那么不用怕, 考完试后, 导师讲解的时候你要注意听…

java 持续集成工具_Jenkins-Jenkins(持续集成工具)下载 v2.249.2官方版--pc6下载站

Jenkins是一款基于java开发的持续集成工具&#xff0c;是一款开源软件&#xff0c;主要用于监控持续重复的工作&#xff0c;为开发者提供一个开发易用的软件平台&#xff0c;使软件的持续集成变成可能。。相关软件软件大小版本说明下载地址Jenkins是一款基于java开发的持续集成…

java中线程调度遵循的原则_深入理解Java多线程核心知识:跳槽面试必备

多线程相对于其他 Java 知识点来讲&#xff0c;有一定的学习门槛&#xff0c;并且了解起来比较费劲。在平时工作中如若使用不当会出现数据错乱、执行效率低(还不如单线程去运行)或者死锁程序挂掉等等问题&#xff0c;所以掌握了解多线程至关重要。本文从基础概念开始到最后的并…

java类构造方法成员方法练习_面向对象方法论总结 练习(一)

原标题&#xff1a;面向对象方法论总结 & 练习(一)学习目标1.面向对象与面向过程2.类与对象的概念3.类的定义&#xff0c;对象的创建和使用4.封装5.构造方法6.方法的重载内容1.面向对象与面向过程为什么会出现面向对象反分析方法&#xff1f;因为现实世界太复杂多变&#x…

mysql 统计查询不充电_MySql查询语句介绍,单表查询,来充电吧

mysql在网站开发中&#xff0c;越来越多人使用了&#xff0c;方便部署&#xff0c;方便使用。我们要掌握mysql,首先要学习查询语句。查询单个表的数据&#xff0c;和多个表的联合查询。下面以一些例子来先简单介绍下单表查询。操作方法01首先看下我们例子用到的数据表&#xff…

MySQL线上优化_线上MySQL千万级大表,如何优化?

前段时间应急群有客服反馈&#xff0c;会员管理功能无法按到店时间、到店次数、消费金额进行排序。经过排查发现是 SQL 执行效率低&#xff0c;并且索引效率低下。图片来自 Pexels应急问题商户反馈会员管理功能无法按到店时间、到店次数、消费金额进行排序&#xff0c;一直转圈…