MySQL索引机制详解(B+树)
一、索引是什么?
索引是为了加速对表中数据行的检索而创建的一种分散存储的数据结构。而且是实现了高级查找算法的数据结构,索引一般以文件形式存储在磁盘上,索引检索需要磁盘I/O操作。
二、为什么要使用索引?
- 索引能极大的减少存储引擎需要扫描的数据量。
- 索引可以把随机IO变成顺序IO。
- 索引可以帮助我们在进行分组、排序等操作时,避免使用临时表。
三、磁盘存取原理
磁盘存取有以下特点:
- 寻道时间(速度慢,费时);
- 旋转时间(速度较快);
- 预读:长度为页的整倍数( 主存和磁盘以页为单位交换数据,一页4K);
- 空间连续性原理:被访问的数据,其所在的位置周围的数据也有更高的可能性被访问。

四、索引是什么实现的?
Indexes是第三方公司提供的可插拔的插件式存储引擎。
MySQL结构体系:
五、为什么选用B+树?
1、Hash索引方式

其实在我们数据库中也使用到了Hash的索引方式,数据库默认有就是这两种实现方式:Hash和B+树,如图所示:

优点:
- 如果是等值查询,哈希索引明显有绝对优势, 前提:键值唯一,而且不涉及到范围查找,模糊匹配,如电话号码就很适合。
缺点:
- 利用Hash存储的话需要将所有的数据文件添加到内存,比较耗费内存空间。
- 哈希索引没办法完成范围查询检索
- 哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询
- 哈希索引也不支持多列联合索引的
- 在有大量重复键值情况下,哈希索引的效率也最左前缀原则是极低的,因为存在哈希碰撞问题
2、二叉树、红黑树索引方式

缺点:
- 太深:数据处的高/深度决定着他的IO操作次数, IO操作耗时大。应先把数据读取效率。
- 太小:每一个磁盘块(节点/页)保存的数据量太小了。
3、B树(B-树)的索引方式

缺点:
- B树的每个节点既有key又有data,但是每个页存储的空间是有限的,如果data较大的话,那么会导致每个节点存储的key数量变小。
- 当存储的数据量很大的时候会导致深度较大,增大查询时候的磁盘IO次数,影响查询性能。
- Mysql查询的时候使用到了大量的范围查找,B树在性能上并不能满足大量范围查找。

B+Tree与B-Tree的区别:
- B+节点关键字搜索采用闭合区间。(MYSQL推崇使用ID作为索引,由于ID是自增的数字类型,只会增大,所以采用向右拓展的一个方式。)
- B+非叶节点不保存数据相关信息, 只保存关键字和子节点的引用。
- B+关键字对应的数据保存在叶子节点中。
- B+叶子节点是顺序排列的, 并且相邻节点具有顺序引用的关系。
选择B+Tree优点:
- B+树是B-树的变种( PLUS版) 多路绝对平衡查找树, 他拥有B-树的优势。
- B+树的叶子节点是顺序排列的,且相邻接点具有顺序引用关系,因此在范围查找时扫库、 表能力更强,同时排序能力更强。
- B+树仅仅在叶子节点存储数据,这样索引文件更小,磁盘读写能力更强。
- B+树的树高较低,索引文件较小,IO次数稳定,查询效率更加稳定。
六、B+树的索引实现方式
查看数据存储位置:
show variables like 'datadir';
1、MyIsam(非聚集索引)
索引和数据分别存储。表定义存在.frm文件中(每个存储引擎都会有)。表中数据存在.MYD文件中。索引存在.MYI文件中。

如果同一张表多个索引:

每个索引都存有每条数据的地址,一旦有变,维护起来比较耗时。
2、InnoDB(聚集索引)

数据就存在索引的叶子节点中。
辅助索引:

其他索引存主键,再从主键索引中找数据。
注意:
- InnoDB是通过B+树结构对主键创建索引,然后叶子节点中储存记录,如果没有主键,那么会选择唯一键,如果没有唯一键,那么会生成一个6位的row_id来作为主键。
- 如果创建索引的键是其他字段,那么在叶子节点中存储的是该记录的主键,然后再通过主键索引找到对应的记录。
为什么不推荐UUID,使用UUID有以下问题:
- UUID一般是32位,长度较长,由于一次预读是4K,这样就增加了读的次数,同时会造成度degree变小,树变高;
- UUID是一个无序的序列,在插入到B+树的时候,设计多次B+树的平衡调整,当树大了的时候性能就会变得很低;
- 由于无序的原因,因此分页查询的时候就会很麻烦。
因此推荐一些自增int、long型的字段作为主键,比如雪花算法。雪花算法(SnowFlake)Java实现
七、索引注意事项
1、联合索引列选择原则
- 经常用的列优先 【 最左匹配原则】
- 选择性( 离散度) 高的列优先【 离散度高原则】(列的离散性越高,选择性就越好。)
- 宽度小的列优先【 最少空间原则】
2、覆盖索引
如果查询列可通过索引节点中的关键字直接返回, 则该索引称之为覆盖索引。
覆盖索引可减少数据库IO, 将随机IO变为顺序IO, 可提高查询性能。
比如创建索引:
create index idx_name_phoneNum on users(name,phoneNum);
查询语句:
select name,phoneNum from user where name=?
可直接从索引树中返回关键字,不会再去查数据内容。
3、其他注意事项
- 索引列的数据长度能少则少。
- 索引一定不是越多越好, 越全越好, 一定是建合适的。
- 匹配列前缀可能用到索引 like 9999%, like %9999%、 like %9999用不到索引。like 9999%得看情况,如果索引列离散性高,就能用到索引,离散性低,就用不到索引。
- Where 条件中 not in 和 <>操作无法使用索引。
- 匹配范围值, order by 也可用到索引。
- 多用指定列查询, 只返回自己想到的数据列, 少用select * 以减少IO。
- 联合索引中如果不是按照索引最左列开始查找, 无法使用索引。在执行常量等值查询时,改变索引列的顺序并不会更改explain的执行结果,因为mysql底层优化器会进行优化,但是推荐按照索引顺序列编写sql语句。
- 联合索引中精确匹配最左前列并范围匹配另外一列可以用到索引。(索引列为name,age的话,name=‘zhangsan’ and age>20)
- 联合索引中如果查询中有某个列的范围查询, 则其右边的所有列都无法使用索引。(索引列为age,name的话,age>20 and name=‘zhangsan’)
附:B+树添加和删除数据图解 (请放大查看)

MySQL索引机制详解(B+树)的更多相关文章
- MySQL索引优化详解
MySQL存储引擎简介 查看命令 a. 查看所使用的MySQL现在已提供什么存储引擎: mysql> show engines; b. 查看所使用的MySQL当前默认的存储引擎: mysql&g ...
- mysql锁机制详解
前言 大概几个月之前项目中用到事务,需要保证数据的强一致性,期间也用到了mysql的锁,但当时对mysql的锁机制只是管中窥豹,所以本文打算总结一下mysql的锁机制. 本文主要论述关于mysql锁机 ...
- 二十二、mysql索引原理详解
背景 使用mysql最多的就是查询,我们迫切的希望mysql能查询的更快一些,我们经常用到的查询有: 按照id查询唯一一条记录 按照某些个字段查询对应的记录 查找某个范围的所有记录(between a ...
- Mysql索引数据结构详解(1)
慢查询解决:使用索引 索引是帮助Mysql高效获取数据的排好序的数据结构 常见的存储数据结构: 二叉树 二叉树不适合单边增长的数据 红黑树(又称二叉平衡树) 红黑树会自动平衡父节点两边的 ...
- 二十三、mysql索引管理详解
一.索引分类 分为聚集索引和非聚集索引. 聚集索引 每个表有且一定会有一个聚集索引,整个表的数据存储在聚集索引中,mysql索引是采用B+树结构保存在文件中,叶子节点存储主键的值以及对应记录的数据,非 ...
- MySQL缓存机制详解(一)
本文章拿来学习用||参考资料:http://www.2cto.com/database/201308/236361.html 对MySql查询缓存及SQL Server过程缓存的理解及总结 一.M ...
- MySQL索引操作命令详解
创建索引: MySql创建索引的语法如下: CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [USING index_type] ON table_ ...
- 图灵学院Java架构师-VIP-【性能调优-Mysql索引数据结构详解与索引优化】
最近报名了图灵学院的架构专题的付费课程,没有赶上6月份开课,中途加入的.错过了多线程的直播课程,只能看录播了
- 0614MySQL的InnoDB索引原理详解
转自http://www.cnblogs.com/shijingxiang/articles/4743324.html MySQL的InnoDB索引原理详解 http://www.admin10000 ...
随机推荐
- centos7下使用yum安装mysql5.7.10
原文地址:http://www.mamicode.com/info-detail-503994.html CentOS7的yum源中默认好像是没有mysql的.为了解决这个问题,我们要先下载mysql ...
- web端调起Windows系统应用程序(exe执行文件),全面兼容所有浏览器
1. 首先,你要有一个exe可执行文件2. 创建注册表创建注册表有两种方式(以“MyApp.exe”为例): 方式一:可视化编辑Win+R 打开运行,输入 regedit 并回车,进入注册表编辑器新建 ...
- 【GStreamer开发】GStreamer基础教程14——常用的element
目标 本教程给出了一系列开发中常用的element.它们包括大杂烩般的eleemnt(比如playbin2)以及一些调试时很有用的element. 简单来说,下面用gst-launch这个工具给出一个 ...
- LeetCode 172. 阶乘后的零(Factorial Trailing Zeroes)
172. 阶乘后的零 172. Factorial Trailing Zeroes 题目描述 给定一个整数 n,返回 n! 结果尾数中零的数量. LeetCode172. Factorial Trai ...
- [转帖]TPC-C解析系列02_OceanBase如何做TPC-C测试
TPC-C解析系列02_OceanBase如何做TPC-C测试 http://www.itpub.net/2019/10/08/3333/ 导语: 蚂蚁金服自研数据库OceanBase登顶TPC- ...
- PHP被忽略的基础知识
目录 下列PHP配置项中,哪一个和安全最不相关:() 字符串比较函数 格林时间 在PHP面向对象中,下面关于final修饰符描述错误的是( ) getdate()函数返回的值的数据类型是:( ) 关于 ...
- java当中JDBC当中请给出一个sql server的helloworld例子
[学习笔记] 1.sql server的helloworld例子: import java.sql.*; public class JdbcHelloSqlServer { public stati ...
- Java的设计模式(5)-- 策略模式
定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换,本模式使得算法可以独立于使用它的客户而变化.策略模式包括以下三种角色 策略(Strategy):策略是一个接口,该接口定义若干个算法标识, ...
- C++_向函数传递对象
向函数传递对象 1. 使用对象作为函数参数 对象可以作为参数传递给函数,其方法与传递其他类型的数据相同. 在向函数传递对象时,是通过传值调用传递给函数的. 因此,函数中对对象的任何修改均不影响调用该函 ...
- C++ new/delete详解及原理
学了冯诺依曼体系结构,我们知道: 硬件决定软件行为,数据都是围绕内存流动的. 可想而知,内存是多么重要.当然,我们这里说的内存是虚拟内存(详情看Linxu壹之型). 1.C/C++内存布局 2.C语言 ...