Mysql索引的数据结构

Mysql索引的数据结构

目录

1.索引

1.1.数据结构

1.1.1.二叉树

1.1.2.红黑树

1.1.3.Hash树

1.1.4.BTree

1.1.5.B+Tree

1.2.索引引擎

1.2.1.MyISAM(因为数据和索引没有在一起所以是非聚集索引)

1.2.2.InnoDB(因为索引和数据都在一起所以也叫做聚集索引)

1.3.联合索引


1.索引

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

1.1.数据结构

1.1.1.二叉树

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分。

首先根据实际问题进行分析:

当我没有使用索引SQL语句查询如下:

select *  from table where Col2 = 23

一个简单的SQL查询需要进行7次磁盘的IO操作(一条一条的向下查询),这样无疑是消耗,所以引入二叉树来进行解决这个问题。

 当我使用二叉树进行数据的存储的时候 ,这个Col2会排序成这种类型,当我们在查询23的时候,这个时候只需要进行4次的磁盘IO就可以找到对应的数据。

这无非解决了我们遇到了直接进行全表查询的问题,但是二叉树的使用有会伴随新的问题的产生。

1.二叉树的定义是每个节点只有两个字数,那么每一层的存储是有限的(当面对MySQL大的数据量的情况下,子叶数据过多,层级过多也会导致大量的IO产生)
2.在特殊情况下,二叉树是存在问题的(如下图所示)

 

在使用有序的自增序列的时候,二叉树就会产生如下的结构。

假设我使用Col1作为索引,二叉树就会存在如上图存在的问题,这样的话使用二叉树的意义就不是很大了。

1.1.2.红黑树

红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。

红黑树是一种特化的AVL树(平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。

红黑树和平衡二叉树的区别,红黑树在结构的变化上还算是比较稳定的。
所以就会导致平衡二叉树相对于红黑树保持更加严格的平衡,所以平衡二叉树的查询是比较快的(但是以多旋的方式保持平衡增加可新增、修改、删除的开销)
这也就是HashMap的树使用的是红黑树而不使用平衡二叉树的原因。

首先我们使用红黑树进行Col2的索引查看。

再次查看Col1的索引排序

红黑树确实解决了二叉树中,序号自增的问题,进行了自旋优化的方式,但是还是没有解决当数据量过大的情况(叶子节点多,层数多,IO多的问题)。

1.1.3.Hash树

哈希树(或哈希特里)是一种持久性数据结构,可用于实现集合和映射,旨在替换纯函数式编程中的哈希表。 在其基本形式中,哈希树在trie中存储其键的哈希值(被视为位串),其中实际键和(可选)值存储在trie的“最终”节点中。

首先Hash树的设定是可以达成目标的要求的,根据Hash值快速定位到指定的位置。

在索引方式的选择上,允许Hash的选择,但是即便是查询很快,但是在实际的建索引的情况,也是很少的应用,这个是为什么?

首先确实解决了查询慢的情况,但是如果遇见范围性的取值情况,Hash就是无可奈何了。只能进行全表扫描一个个比较,这个并不是我们想要看到的情况。

1.1.4.BTree

在讲解定义BTree之前我们可以首先看下Btree的示意图,示意图如下所示:

BTree的特点

叶节点具有相同的深度,叶节点的指针为空
所有索引元素不重复
节点中的数据索引从左到右递增排列

在Mysql中默认的是每个子叶块的大小为16K

Btree能完美的解决我们现在的实际情况,但是我们需要观察下,在每一个索引的下面都会带着对应的data数据的,当表中的数据字段少还可以勉强接受,但是字段如果很多的话,每一个叶块所能存放的索引也是很少的,所以这个也不是很符合要求。

1.1.5.B+Tree

在讲解B+Tree之前我们需要先看下B+Tree的示意图,示意图如下所示。

 B+Tree的特点如下:

非叶子节点不存储data,只存储索引(冗余),可以放更多的索引
叶子节点包含所有索引字段
叶子节点用指针连接,提高区间访问的性能

B+Tree是否解决了实际的问题?

第一:每一个叶子节点不会专门的带有Data的数据了,那么每个叶子节点存放的数据就会更多,估计到了第三层的时候就能打倒2000W左右的数据存储(解决了二叉树、红黑树、BTree问题)
第二:解决了二叉树连续递增的问题(不仅解决了,这里之后还更加依赖了整形类的数据递增,因为这样的话,才能更好的组装B+Tree的结构,不是递增的情况下有中位数据的产生,有可能导致
数据结构的变化,对于数据库来说也是很大的开销)(解决了二叉树问题)
第三:在最底层的时候会有环行链(首尾相连)的结构在里面,解决了Hash树的范围查询的问题(解决了Hash树问题)

1.2.索引引擎

在MySQL的索引引擎中主流的搜索引擎有两种,一种是MyISAM,另一种是InnoDB

1.2.1.MyISAM(因为数据和索引没有在一起所以是非聚集索引)

首先查看MyISAM本质是在数据中的存储方式

 

我的User表定义成MyISAM类型,在DATA数据中会有三个文件

*.frm 存储表结构
*.MYD 存储表数据
*.MYI存储表索引

实际的查询逻辑如下图所示:

首先查询MYI的数据确定出数据存储的位置,然后再根据位置信息(0x07)定位到整条数据。

然后通过位置信息查找MYD文件,直接获取到数据的内容。

1.2.2.InnoDB(因为索引和数据都在一起所以也叫做聚集索引)

查看InnoDB的存储方式

表sys_uesr_role使用的是InnoDB进行定义的,在Data中会有两个文件数据

*.frm 存储表结构
*.idb 存储的是索引和数据

实际的实现逻辑如下图所示:

主键索引:

非主键索引:

问题:

为什么InnoDB表必须有主键,并且推荐使用整型的自增主键?
答:没有主键的话,系统会默认的使用 rowid作为主键进行排序,但是rowid是默认的,大小是不确定的,在插入的时候可能会导致索引树结构的变更。这也同时回答了为什么用整数自增型来作为主键
为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)
答:非主键这么存储的原因是因为,为了只是维护一份数据,假设如果非主键数据也存在Data,idb的数据是按照倍数增加,而且如果非主键索引存储了数据,
就会包含一致性事务在里面,白白浪费了很多无用的开销。

1.3.联合索引

联合索引有最左原则

猜你喜欢

转载自blog.csdn.net/baidu_31572291/article/details/115163734