欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

索引的分类与具体讲解

程序员文章站 2024-03-16 20:58:22
...

原理:

B树

b树(balance tree)和b+树应用在数据库索引,可以认为是m叉的多路平衡查找树,但是从理论上讲,二叉树查找速度和比较次数都是最小的,为什么不用二叉树呢?
因为我们要考虑磁盘IO的影响,它相对于内存来说是很慢的。数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘页(对应索引树的节点)。所以我们要减少IO次数,对于树来说,IO次数就是树的高度,而“矮胖”就是b树的特征之一,它的每个节点最多包含m个孩子,m称为b树的阶,m的大小取决于磁盘页的大小。

一个M阶的b树具有如下几个特征:

定义任意非叶子结点最多只有M个儿子,且M>2;
根结点的儿子数为[2, M];
除根结点以外的非叶子结点的儿子数为[M/2, M],向上取整;
非叶子结点的关键字个数=儿子数-1;
所有叶子结点位于同一层;
k个关键字把节点拆成k+1段,分别指向k+1个儿子,同时满足查找树的大小关系。
有关b树的一些特性,注意与后面的b+树区分:

**1. 关键字集合分布在整颗树中;

  1. 任何一个关键字出现且只出现在一个结点中
  2. 搜索有可能在非叶子结点结束
  3. 其搜索性能等价于在关键字全集内做一次二分查找;**
    索引的分类与具体讲解
    索引的分类与具体讲解
    索引的分类与具体讲解

B+树

b+树,是b树的一种变体,查询性能更好。m阶的b+树的特征:

1. 有n棵子树的非叶子结点中含有n个关键字(b树是n-1个),这些关键字不保存数据,只用来索引,所有数据都保存在叶子节点(b树是每个关键字都保存数据)

2 所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接

3 所有的非叶子结点可以看成是索引部分,结点中仅含其子树中的最大(或最小)关键字。

4 通常在b+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点。

5 同一个数字会在不同节点中重复出现,根节点的最大元素就是b+树的最大元素。

索引的分类与具体讲解

区别

**b+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更“矮胖”;
b+树查询必须查找到叶子节点,b树只要匹配到即可不用管元素位置,因    此b+树查找更稳定(并不慢);
对于范围查找来说,b+树只需遍历叶子节点链表即可,b树却需要重复地中序遍历:**

索引的分类与具体讲解

索引的分类与具体讲解

索引分类

聚簇索引

聚簇:表示数据行和相邻的键值紧凑地存储在一起。一个表只能有一个聚簇索引
索引的分类与具体讲解
上图中310,202,203,101,104等等都可以想成内存地址
以E开头的都是我们自己建立的索引列的数据
索引的分类与具体讲解
其实像上图这样的在mysql中就是一页,innodb引擎是按页进行IO的。

mysql页的详细讲解

聚簇索引的使用条件与不适用条件

索引的分类与具体讲解
聚簇索引的优点:

可以把相关数据保存在一起

数据访问更快(聚集索引将索引和数据保存在同一个b-tree中)

使用覆盖索引扫描的查询可以直接使用页节点中的主键值

聚簇索引的缺点:

聚簇数据提高了IO性能,如果数据全部放在内存中,则访问的顺序就没那么重要了

插入速度严重依赖插入顺序。按主键的顺序插入是速度最快的。但如果不是按照主键顺序加载数据,则需在加载完成后最好使用optimize table重新组织一下表

更新聚簇索引列的代价很高。因为会强制innod将每个被更新的行移动到新的位置

基于聚簇索引的表在插入新行,或主键被更新导致需要移动行的时候,可能面临页分裂的问题。页分裂会导致表占用更多的磁盘空间。

聚簇索引可能导致全表扫描变慢,尤其是行比较稀疏,或由于页分裂导致数据存储不连续的时

InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树上再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据

非聚簇索引

索引的分类与具体讲解

索引的分类与具体讲解

非聚簇索引的使用条件

索引的分类与具体讲解
MyISM使用的是非聚簇索引,非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树

聚簇索引和非聚促索引的比较

索引的分类与具体讲解
索引的分类与具体讲解

我们重点关注聚簇索引,看上去聚簇索引的效率明显要低于非聚簇索引,因为每次使用辅助索引检索都要经过两次B+树查找,这不是多此一举吗?聚簇索引的优势在哪

1 由于行数据和叶子节点存储在一起,这样主键和行数据是一起被载入内存的找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来组织数据,获得数据更快。

2 辅助索引使用主键作为"指针" 而不是使用地址值作为指针的好处是,减少了当出现行移动或者数据页分裂时辅助索引的维护工作,使用主键值当作指针会让辅助索引占用更多的空间,换来的好处是InnoDB在移动行时无须更新辅助索引中的这个"指针"。也就是说行的位置(实现中通过16K的Page来定位,后面会涉及)会随着数据库里数据的修改而发生变化(前面的B+树节点分裂以及Page的分裂),使用聚簇索引就可以保证不管这个主键B+树的节点如何变化,辅助索引树都不受影响。

唯一索引

索引的分类与具体讲解
索引的分类与具体讲解

组合索引

索引的分类与具体讲解

反转索引

反转索引精讲

位图索引

索引的分类与具体讲解

索引的分类与具体讲解

小结

小结:我们不难发现除了位图索引之外其他的上述所讲的索引都是基于B+树实现的,可见B+树的效率是十分高的。

相关标签: 索引 mysql