图解 MySQL 索引,清晰易懂,写得太好了!
点击关注公众号,回复“1024”获取2TB学习资源!
什么是索引?
索引是辅助存储引擎高效获取数据的一种数据结构。
很多人形象的说索引就是数据的目录,便于存储引擎快速的定位数据。
索引的分类
我们经常从以下几个方面对索引进行分类
从数据结构的角度对索引进行分类
B+tree
Hash
Full-texts索引
从物理存储的角度对索引进行分类
聚簇索引
二级索引(辅助索引)
从索引字段特性角度分类
主键索引
唯一索引
普通索引
前缀索引
从组成索引的字段个数角度分类
单列索引
联合索引(复合索引)
数据结构角度看索引
下表是MySQL常见的存储引擎InnoDB,MyISAM和Memory分别支持的索引类型
在实际使用中,InnoDB作为MySQL建表时默认的存储引擎
对上表进行横向查看可以了解到,B+tree是MySQL中被存储引擎采用最多的索引类型。
这里浅尝辄止的谈一下B+tree 与 Hash 和红黑树的区别。
B+tree和B-tree
1970年,R.Bayer和E.Mccreight提出了一种适用于外查找的平衡多叉树——B-树,磁盘管理系统中的目录管理,以及数据库系统中的索引组织多数采用B-Tree这种数据结构。--数据结构C语言版第二版 严蔚敏
B+tree是B-Tree的一个变种。(哦,对了,B-tree念B树,它不叫B减树。。。)
B+tree只在叶子节点存储数据,而B-tree非叶子节点也存储数据。
因此,B+tree单个节点的数量更小,在相同的磁盘IO下能查询更多的节点。
另外B+tree叶子节点采用单链表链接适合MySQL中常见的基于范围的顺序检索场景,而B-tree无法做到这一点。
B+tree和红黑树
对于有N个叶子节点的B+tree,搜索复杂度为O(logdN) ,d是指degree是指B+tree的度,表示节点允许的最大子节点个数为d个,在实际的运用中d值是大于100的,即使数据达到千万级别时候B+tree的高度依然维持在3-4左右,保证了3-4次磁盘I/O就能查到目标数据.
从上图中可以看出红黑树是二叉树,节点的子节点个数最多为2个,意味着其搜索复杂度为O(logN),比B+树高出不少,因此红黑树检索到目标数据所需经理的磁盘I/O次数更多。
B+tree索引与Hash表
范围查询是MySQL数据库中常见的场景,而Hash表不适合做范围查询,Hash表更适合做等值查询,另外Hash表还存在Hash函数选择和Hash值冲突等问题。
因为这些原因,B+tree索引要比Hash表索引有更广的适用场景。
物理存储角度看索引
MySQL中的两种常用存储引擎对索引的处理方式差别较大。
InnoDB的索引
首先看一下InnoDB存储引擎中的索引,InnoDB表的索引按照叶子节点存储的是否为完整表数据分为聚簇索引和二级索引。
全表数据就是存储在聚簇索引中的。
聚簇索引以外的其它索引叫做二级索引。
下面结合实际的例子介绍下这两类索引。
create table workers(id int(11) not null auto_increment comment '员工工号',name varchar(16) not null comment '员工名字',sales int(11) default null comment '员工销售业绩',primary key (id)) engine InnoDBAUTO_INCREMENT = 10default charset = utf8;insert into workers(id, name, sales)values (1, '江南', 12744);insert into workers(id, name, sales)values (3, '今何在', 14082);insert into workers(id, name, sales)values (7, '路明非', 14738);insert into workers(id, name, sales)values (8, '吕归尘', 7087);insert into workers(id, name, sales)values (11, '姬野', 8565);insert into workers(id, name, sales)values (15, '凯撒', 8501);insert into workers(id, name, sales)values (20, '绘梨衣', 7890);
我们现在自己的测试数据库中创建一个包含销售员信息的测试表workers
包含id(主键),name,sales三个字段,指定表的存储引擎为InnoDB。
然后插入8条数据
这个例子当中,workers表的聚簇索引建立在字段id上
为了准确模拟,我们先把主键id插入b+tree得到下图
然后在此图基础上,我画出了高清版。
从图中可以看到,聚簇索引的每个叶子节点存储了一行完整的表数据,叶子节点间采用单向链表按id列递增连接,可以方便的进行顺序检索。
InnoDB表要求必须有聚簇索引,默认在主键字段上建立聚簇索引,在没有主键字段的情况下,表的第一个NOT NULL 的唯一索引将被建立为聚簇索引,在前两者都没有的情况下,InnoDB将自动生成一个隐式自增id列并在此列上创建聚簇索引。
接着来看二级索引
还以刚才的workers表为例
我们在name字段上添加二级索引index_name
alter table workers add index index_name(name);
同样我们画出了二级索引index_name的B+tree示意图
图中可以看出二级索引的叶子节点并不存储一行完整的表数据,而是存储了聚簇索引所在列的值,也就是workers表中的id列的值。
这两张示意图中B+tree的度设置为了3 ,这也主要是为了方便演示。
实际的B+tree索引中,树的度通常会大于100。
说了聚簇索引和二级索引 肯定要提到回表查询。
由于二级索引的叶子节点不存储完整的表数据,所以当通过二级索引查询到聚簇索引的列值后,还需要回到局促索引也就是表数据本身进一步获取数据。
比如说我们要在workers表中查询 名叫吕归尘的人
select * from workers where name='吕归尘';
这条sql通过name='吕归尘'的条件
在二级索引index_name中查询到主键id=8 ,接着带着id=8这个条件
进一步回到聚簇索引查询以后才能获取到完整的数据,很显然回表需要额外的B+tree搜索过程,必然增大查询耗时。
需要注意的是通过二级索引查询时,回表不是必须的过程,当Query的所有字段在二级索引中就能找到时,就不需要回表,MySQL称此时的二级索引为覆盖索引或称触发了索引覆盖。
select id,name from workers where name='吕归尘';
这句sql只查询了id,和name,二级索引就已经包含了Query所以需要的所有字段,就无需回表查询。
explain select id,name from workers where name='吕归尘';
使用explain查看此条sql的执行计划
执行计划的Extra字段中出现了Using where;Using index 表明查询触发了索引index_name的索引覆盖,且对索引做了where筛选,这里不需要回表。
下面做对比,查询一下没有索引的
explain select id,name,sales from workers where name='吕归尘';
Extra为Using Index Condition 表示会先条件过滤索引,过滤完索引后找到所有符合索引条件的数据行,随后用 WHERE 子句中的其他条件去过滤这些数据行。Index Condition Pushdown (ICP)是MySQL 5.6 以上版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式。ICP开启时的执行计划含有 Using index condition 标示 ,表示优化器使用了ICP对数据访问进行优化。
这次我们简化来理解,不考虑ICP对数据访问的优化,
当关闭ICP时,Index仅仅是data access的一种访问方式,存储引擎通过索引回表获取的数据会传递到MySQL Server 层进行WHERE条件过滤。
Extra为Using where 只是提醒我们MySQL将用where子句来过滤结果集。这个一般发生在MySQL服务器,而不是存储引擎层。一般发生在不能走索引扫描的情况下或者走索引扫描,但是有些查询条件不在索引当中的情况下。
这里表明没有触发索引覆盖,进行回表查询。
MyISAM的索引
说完了InnoDB的索引,接下来我们来看MyISAM的索引
以MyISAM存储引擎存储的表不存在聚簇索引。
MyISAM索引B+tree示意图
MyISAM表中的主键索引和非主键索引的结构是一样的,从上图中我们可以看到
他们的叶子节点是不存储表数据的,节点中存放的是表数据的地址,所以MyISAM表可以没有主键。
MyISAM表的数据和索引是分开的,是单独存放的。
MyISAM表中的主键索引和非主键索引的区别仅在于主键索引B+tree上的key必须符合主键的限制,
非主键索引B+tree上的key只要符合相应字段的特性就可以了。
索引字段特性角度看索引
主键索引
建立在主键字段上的索引
一张表最多只有一个主键索引
索引列值不允许为null
通常在创建表的时候一起创建
唯一索引
建立在UNIQUE字段上的索引就是唯一索引
一张表可以有多个唯一索引,索引列值允许为null
我们演示创建索引
create table persons(id int(11) not null auto_increment comment '主键id',eno int(11) comment '工号',eid int(11) comment '身份证号',veid int(11) comment '虚拟身份证号',name varchar(16) comment '名字',primary key (id) comment '主键索引',UNIQUE key (eno) comment 'eno唯一索引',UNIQUE key (eid) comment 'eid唯一索引') engine = InnoDBauto_increment = 1000default charset = utf8;alter table personsadd unique index index_veid (veid) comment 'veid唯一索引';
通过show index from persons;命令我们看到已经成功创建了三个唯一索引。
普通索引
主键索引和唯一索引对字段的要求是要求字段为主键或unique字段,
而那些建立在普通字段上的索引叫做普通索引,既不要求字段为主键也不要求字段为unique。
前缀索引
前缀索引是指对字符类型字段的前几个字符或对二进制类型字段的前几个bytes建立的索引,而不是在整个字段上建索引。
例如,可以对persons表中的name(varchar(16))字段 中name的前5个字符建立索引。
create index index_name on persons (name(5)) comment '前缀索引';
show index from persons;
前缀索引可以建立在类型为
char
varchar
binary
varbinary
的列上,可以大大减少索引占用的存储空间,也能提升索引的查询效率。
索引列的个数角度看索引
建立在单个列上的索引为单列索引
上文演示的都是单列索引
建立在多列上的称为联合索引(复合索引)
演示一下联合索引
create index index_id_name on workers(id,name) comment '组合索引';
这条语句在我们演示表workers中建立id,name这两个字段的联合索引。
借助show index命令查看索引的详细信息 操作后结果如下:
虽然详细信息当中列出了两条关于联合索引的条目,但并不表示联合索引是建立了多个索引,联合索引是一个索引结构,这两个条目表示的是组合索引中字段的具体信息,按建立索引时的书写顺序排序。
同样我们来看下联合索引的B+tree示意图
从图中看到
组合索引的非叶子节点保存了两个字段的值作为B+tree的key值,当B+tree上插入数据时,先按字段id比较,在id相同的情况下按name字段比较。
作者:shuaibing90 来源:
xysycx.cn/articles/2020/12/05/1607146183637.html
推荐阅读 点击标题可跳转
如何让手机 1 秒打开健康码,任何机型!
被裁了!39 岁阿里 P9,攒下 1.5 亿....
深入理解 Linux I/O 系统!有图有真相
这 4 种 Redis 常用运维工具都不会?你算啥运维人
谁再说不熟悉 Linux 命令,就把这个给他扔过去!
2021 年年度蕞佳开源软件!
火狐,恶心到我了。。。
这是我裸辞接单第一个月的收入
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。
随手在看、转发是最大的支持!
图解 MySQL 索引,清晰易懂,写得太好了!相关推荐
- 图解 MySQL 索引,清晰易懂,写得太好了…
作者:shuaibing90 来源:https://www.xysycx.cn/articles/2020/12/05/1607146183637.html 什么是索引? 索引是辅助存储引擎高效获取数 ...
- 第四十九期:大牛总结的MySQL锁优化,写得太好了!
随着 IT 技术的飞速发展,各种技术层出不穷,让人眼花缭乱.尽管技术在不断更新换代,但是有些技术依旧被一代代 IT 人使用至今. 作者:崔皓 随着 IT 技术的飞速发展,各种技术层出不穷,让人眼花缭乱 ...
- mysql 栅格数据结构_图解Mysql索引的数据结构!看不懂你来找我
(一)关于索引 索引是帮助Mysql更加高效获取数据的一种数据结构,索引的使用很简单,但是如果不能理解索引底层的数据结构的话,就谈不上去优化索引了. (二)B+树 Mysql的索引用的是B+树,他具有 ...
- mysql索引背后的数据结构_图解Mysql索引的数据结构!看不懂你来找我
听说微信搜索<Java鱼仔>会变更强哦! 本文收录于JavaStarter ,里面有我完整的Java系列文章,学习或面试都可以看看哦 (一)关于索引 索引是帮助Mysql更加高效获取数据的 ...
- 【Java】图解 Spring 循环依赖,写得太好了
1.概述 转载:http://www.javastack.cn/article/2020/spring-circular-dependencies-write-so-well/ 前言 Spring如何 ...
- 整型索引查询mysql是不是快点_图解Mysql索引的数据结构!看不懂你来找我
听说微信搜索<Java鱼仔>会变更强哦! 本文收录于JavaStarter ,里面有我完整的Java系列文章,学习或面试都可以看看哦 (一)关于索引 索引是帮助Mysql更加高效获取数据的 ...
- 图解 Spring 循环依赖,写得太好了!
作者 | Vt 来源 | https://urlify.cn/jymi2q Spring如何解决的循环依赖,是近两年流行起来的一道Java面试题. 其实笔者本人对这类框架源码题还是持一定的怀疑态度的. ...
- 图解 MySQL 索引:B-树、B+树
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:http://tinyurl.com/y5ymnj9a 一. ...
- 图解 MySQL 索引:B-树、B+树,终于搞清楚了!
看了很多关于索引的博客,讲的大同小异.但是始终没有让我明白关于索引的一些概念,如B-Tree索引,Hash索引,唯一索引-. 或许有很多人和我一样,没搞清楚概念就开始研究B-Tree,B+Tree等结 ...
最新文章
- MFC控件编程之复选框单选框分组框
- [转]笑话: 耐力惊人的三只乌龟
- iOS10 UI教程管理层次结构
- xml验证 java代码,使用Java代码进行XML验证
- 员工转正申请书_员工有了归属感 企业实现大发展!通机股份在党工共建中摸索经验...
- Vue报错bash: vue: command not found或者vue ui没有反应:官方修改成新的命令了
- 《Node.js 入门系列》—— 一些简单的排错方法(一)
- github和pypi_如何将GitHub用作PyPi服务器
- 12. OD-XOFTSPY监控系统软件,通过windows API进行破解(双重验证,聪明的加密师)
- python处理txt文件的一种情况
- sql truncate_SQL Truncate和SQL Delete语句的内部
- RedHat 8.0软件包组--桌面类
- python3.5------用户的三次验证
- 第八章 拦截器机制——《跟我学Shiro》[张开涛]
- android 极光IM集成及使用
- 程序员利用Python定时抓取微博评论
- Jmeter 中的BeanShell使用
- STC单片机 定时器时钟FOSC 1T 12T、定时器模式
- alt复制选区就会卡 ps_ps复制选区快捷键是什么
- 使用 Certbot 自动申请并续订阿里云 DNS 免费泛域名证书
热门文章
- 已知地址块中的一个地址是 167.199.170.82/27,求这个地址块的地址数、首地址以及末地址各是多少?
- Windows11 Edge斯巴达浏览器开启IE模式 解决Win11没有自带IE浏览器的问题
- 论文摘要(一):Reinforcement Learning on Variable Impedance Controller for High-Precision Robotic Assembly
- 美和易思·湖南生机职院校企共建专业技能抽查标准认证会成功召开
- eclipse的workspace删除
- 2021年登高架设考试总结及登高架设模拟试题
- 《OpenHarmony开源鸿蒙学习入门》-- 系统相机应用源码解析(一)
- 2022安全员-B证考试练习题及模拟考试
- NeurIPS 2020 | MiniLM:通用预训练模型压缩方法
- mqttnet+emqx实现消息订阅与发布