首先介绍两种存储的数据结构:
B树
定义:(让每个索引块尽可能多的存储信息,然后查询过程中尽可能少的IO次数)
- 根节点至少包括两个孩子
- 树中每个节点最多含有m个孩子(M>=2)
- 除根节点和叶子节点外,其他每个节点至少有ceil(m/2)个孩子(取上限)
- 所有叶子节点都位于同一层
B+树
B+树和B树类似,但多了几条规则 :
- 非叶子结点的子树指针个数与关键字(节点中的元素个数)个数相同
- 非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(B-树是开区间)
- 所有叶子结点有一个链指针 所有关键字都在叶子结点出现
- 只有叶子节点有Data域
- 可以看到最主要的区别就是在叶子节点,叶子节点通过一个DATA将所有叶子节点链成一个链表,并且只有叶子节点有data域(data域就是索引指向的磁盘地址)。
介绍完B树与B+树的数据结构后,再来谈谈为很么mysql的InnDb引擎采用B+树的索引方式,而不是采用其他的数据结构?
- 二分查找树的局限性:极端情况下会退化为链表,查询效率会大大增加
- AVL平衡二叉树与红黑树:假如B+树有一百个关键字,那么3层的B+树可以容纳大概1000000多个关键词,而红黑树与AVL树至少要20层,查找时需要大量的IO操作。
- 数组与链表:链表查询速度慢,数组需要开辟大量的连续空间
- 哈希表:哈希表无法实现范围查询
- B树:B树的每个节点都有Data域(data域就是索引指向的磁盘地址)。而B+树只有叶子节点存放数据,所以B+树相比于B树的IO代价更低,而且B+树还支持范围查询,查询效率更加稳定(每次的查询数据必须从走一条从根节点到叶子节点的路,所有的关键字查询的长度相同)。
- B树的使用场景:B树大多用于磁盘上用于查找磁盘的地址。由于磁盘会有大量的数据,有可能没有办法一次将需要的所有数据加入到内存中,所以只能逐一加载磁盘页,每个磁盘页就对应一个节点,而对于B树来说,B树很好的将树的高度降低了,这样就会减少IO查询次数,虽然一次加载到内存的数据变多了,但速度绝对快于AVL或是红黑树的。
稀疏索引与密集索引的区别:
密集索引:
稀疏索引:
- 密集索引文件中的每个搜索码都对应一个索引值
- 稀疏索引文件只为搜索码的某些值建立索引项
- 密集索引比稀疏索引更快的定位一条记录
- 稀疏索引所占用的空间小,并且插入和删除时所维护的开销也小
在MySQL的InnoDB中,关于密集索引的知识点:
- 若一个主键被定义为,则该主键为密集索引
- 若没有主键被定义,该表的第一个唯一非空索引则作为密集索引
- 若不满足以上条件,InnoDB内部会生成一个隐藏主键(密集索引)