MySql索引及使用实现的数据结构

Posted 小艾路西里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySql索引及使用实现的数据结构相关的知识,希望对你有一定的参考价值。

1. 索引简介

索引是帮助MySql高效获取数据的排好序的数据结构

在数据量大的时候,索引可以大大提高MySQL的检索速度

索引实际也是一张表,该表中保存了主键与索引字段,并指向实体类的记录,所以索引列也是要占用空间的

虽然索引大大提高了查询效率,同时却也降低更新表的速度

2. MySql索引的数据结构

实现索引的数据结构:二叉树、红黑树、Hash表、B+tree

最开始的索引的实现是二叉树,后来慢慢改进,到现在MySql的索引只有俩种实现方式,Hash表和B+Tree,但Hash表不常用

为什么mysql索引不采用红黑树而采用b树?

首先要知道数据库索引是存储在外部磁盘上的

当利用索引查询的时候,不可能把整个索引全部加载到内存,只能逐一加载每个磁盘页,磁盘页对应索引树的节点

那么Mysql衡量查询效率的标准就是磁盘IO次数。

如果使用二叉树作为索引结构,那么磁盘的IO次数和索引树的高度是相关的

因为当数据量过大时,使用红黑树树的高度会很高,所以对硬盘的读取次数会比较多,时间就比较慢

二叉树:右边子节点存储大于父节点

红黑树:红黑树和平衡二叉树(左右两个子树的高度差不超过1)比较像,节点是红色或黑色,根节点是黑色,叶子节点都是黑色的空节点
在这里插入图片描述

(1) Hash表

在这里插入图片描述
来自诸葛老师视频的图

Hash表的查询流程:

① 通过hash算法计算散列值,然后将散列值存储到一个数组(哈希桶)中

② 将数据(表的数据)和对应硬盘存储地址存储到链表中

③ 查找时通过散列值找到对应数组(哈希桶)位置,遍历链表,找到查找的数据后取出存储地址,从而去到硬盘中定位这一行数据

Hash不常使用的原因:

hash冲突,不支持范围查询(主要原因) 比如<,>运算符

(2) B+Tree(B+树)

在了解B+Tree前,要先知道B Tree(B树)

B树:

B树和平衡二叉树 的差别就是 B树 属于多叉树,又名平衡多路查找树,即一个结点的查找路径不止左、右两个,而是有多个

数据库索引技术里大量使用B树和B+树的数据结构,一个结点存储多个值(索引)

data是数据在硬盘上的存储地址
在这里插入图片描述来自诸葛老师视频的图

节点储存的索引数量可以设置,下例图是2个索引(3条路径)
在这里插入图片描述
B+Tree(在b树上做了优化得到的)
在这里插入图片描述

B+Tree和BTree的区别:

非叶子节点只存储索引 (为了更多的存储索引 mysql设置了16kb搬到内存上去的空间大小)

② 有索引重复(冗余) 比如下例14 20 49 都有重复

叶子节点用指针连接,可以实现区间(同层)访问 利用这一点也实现了范围查询 (比如下图要查找20<col<50,那么直接定位20和50,取中间的就是结果)

索引的定位查找采用二分查找法

推荐一个数据结构可视化测试网站,可以对数据结构进行测试https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

MySql会将要插入B+Tree中的索引先排好序,再插入,因为叶子节点排好序这一点特性才能实现范围查询

3. 索引的分类

(1) 主键索引 (PRIMARY KEY)

主键不可重复,只能有一个列作为主键

(2) 唯一索引 (UNIQUE KEY)

列中的数据不可重复,但多个列都可以作为唯一索引

(3) 常规索引(KEY/INDEX)

默认使用 index 或 key 关键字来创建

(4) 全文索引(FULLTEXT)

在特点的数据库引擎下才有,例如MyISAM
用于快速定位数据

4. 创建索引的语法

(1) 创建单个索引的语法:CREATE INDEX 索引名 on 表名(字段名)

(2) 创建联合索引的语法:CREATE INDEX 索引名 on 表名(字段名1,字段名2)

补充:为什么加入索引能提高查询速度?

例如以下这个这个表,当不添加索引时,需要挨个查找,而因为数据是存储在磁盘上的,每查找一次,也就是读取一次,就会对磁盘做一次IO操作,所以速度会很慢

比如select from t where t.Col2 = 89,就会挨行去查找每一行数据,然后获取Col2去和89进行对比,才能拿到数据

而如果采用索引 (最早期的索引是使用的二叉树,这里以右边的二叉树为例) ,在建立索引的时候,会将Col值存储到一棵二叉树上,每一个节点都会存储一个<key,value> value即是对于的存储地址(磁盘文件地址) 比如34就是0x07 89是0x77

使用索引查询时,从根节点查找,我们都知道对于二叉树的存储,右边子节点存储大于父节点,所以查询的时候,从根节点34出发,因为89>34,所以走右边的节点,发现下一个节点值是89,进行对比89=89成立,就能获取对应的key(存储地址),通过该key就可以直接定位磁盘中的存储地址,获取到数据

在这里插入图片描述

5. 联合索引

最左前缀原则

如果创建了(a, b, c)的联合索引,那么其实相当于创建了(a)、(a,b)、(a,b,c)三个索引,在索引查找的时候,总是会先对比最左边的,再依次往右,这被称为最左前缀原则

以下图和对应的sql查询语句来理解该原则
以index(a,b,c)复合索引为例:
如果使用以下的sql查询语句

select * from employees where name = 'Bili' and age = 31;

此时会先根据name索引去定位Bili,然后再通过age去定位31

select * from employee where age = 30 and position = 'dev';

此时不会通过索引去查找数据,因为where后面只有根据age和position去查找,相当于是通过(age,position)去查找

而创建联合索引的时候,第一个值是name,相当于创建的是(name),(name,age),(name,age,position)这三个索引

所以不存在(age,position)这样一个索引,就只能通过普通的逐行查找,这也就体现了最左前缀原则

6. MySql数据库索引存储引擎

(1) myisarm

特点:数据和Index分开存储,即存放在不同文件(非聚集索引),已经过时

查询流程:通过index存储的存储地址(value data)从而去硬盘对应数据的存储地址找到数据
在这里插入图片描述

(2) innodb :数据(字段)、data(value 存储地址)、Index(索引)存放在一个文件内(聚集索引)

查询流程就是B+Tree的查询方式,由于数据和Index、data绑定在一起,所以不需要再额外的使用对硬盘IO操作,比myisarm更快,也更常用
在这里插入图片描述
为什么推荐使用整形的自增主键?
因为如果不自增,在增加索引的时候,插入到现有的B+Tree中,可能会导致B+Tree变动很大,比如叶子节点容量分裂,根节点增加元素等来达到树平衡,比较耗时
而采用自增永远是在叶子节点的右方开辟新的存储索引的容量空间

以上是关于MySql索引及使用实现的数据结构的主要内容,如果未能解决你的问题,请参考以下文章

Mysql索引分类及实现原理

06: mysql索引查找原理及调优

php教程:MySql数据库索引原理

MySQL中查询表及索引大小的方法

mysql索引原理及优化

Oracle与Mysql主键索引及分页的区别小结