数据库索引简介

https://blog.csdn.net/suifeng3051/article/details/52669644

https://zhuanlan.zhihu.com/p/23624390

目录

1. 索引的优点

2. 聚集索引和非聚集索引

3. 复合索引

4. B+树

5. MySQL数据库常见两种引擎

6. 索引的优化


1. 索引的优点

索引是基于平衡树(左右子树高度相差小于1 的查找树,注意,不一定是二叉的,往往是多叉的),通过索引进行查找会比遍历查找的效率提高很多,此外,还有用哈希桶做索引的数据结构,但主流还是基于平衡树。

索引的优点这么明显,那么他只有好处没有缺点吗?

2. 聚集索引和非聚集索引

一般建表时会要求指定主键,一个没加主键的表,数据会无序地放置在磁盘存储器上,如果给表指定了主键,那么表在磁盘上的存储结构就由整齐排列的结构变成了树状结构,也就是平衡树的结构。用主键建立的索引就是聚集索引。(用了那么久的数据库,终于知道为什么每次建表的时候一定要指定主键,而且主键不能为空,可以指定id为主键,且id递增)。主键的作用就是将表的数据格式转换成索引的格式进行存储。

如上图所示,只有子节点才存放真正的数据,其他节点只存放索引。

敲黑板,索引能让数据库的查询数据的速度上升,而使写入数据的速度下降,原因很简单,因为平衡二叉树这个结构必须一直维持在一个正确的状态,增删改数据都会平衡树各节点中的索引数据内容,破坏树的结构,因此,DBMS必须去重新梳理树的结构以保证它的正确,这会带来不小的性能开销,也就是为什么索引会给查询以外的操作带来副作用的原因。

非聚集索引:非聚集索引和聚集索引的区别就是,非聚集索引是在主键以外的其他字段上建立的索引,(这个区别也太小了吧???不要急),如果给表的多个字段加上索引,那么各个索引之间互相不影响。每给字段增加一个索引,就是将该字段复制一份用于生成索引。因此,给表添加索引,会增加表的面积,占用磁盘存储空间。

非聚集索引和聚集索引的主要区别在于,通过聚集索引可以查找到需要查找的数据,而通过非聚集索引可以查到记录对应的键值,再使用主键的值通过聚集索引查找到需要的数据。

why,注意,非聚集索引建立时只是将该字段复制一份,它并不包含所有的数据,所以非聚集索引只能查找到主键。

 

不管以任何方式查询表,最终都要利用主键通过聚集索引来定位数据,聚集索引(主键)是通往真实数据所在的唯一路径。(不要问为什么,上面已经解释了)

唯一真的就那么绝对吗???

3. 复合索引

有一种例外可以不使用聚集索引就能查询出所需要的数据,这种非主流的索引称之为[覆盖索引]查询,也就是平时所说的符合索引或多字段索引查询。上面已经说过,为某一个字段建立索引时,字段的内容会同步到索引中,如果为一个字段建立两个索引,那么这两个字段的内容都会被同步至索引中。

先看下面这个SQL语句

//建立索引

create index index_birthday on user_info(birthday);

//查询生日在1991年11月1日出生用户的用户名

select user_name from user_info where birthday = '1991-11-1'

这句SQL语句的执行过程如下

首先,通过非聚集索引index_birthday查找birthday等于1991-11-1的所有记录的主键ID值

然后,通过得到的主键ID值执行聚集索引查找,找到主键ID值对就的真实数据(数据行)存储的位置

最后, 从得到的真实数据中取得user_name字段的值返回, 也就是取得最终的结果

我们把birthday字段上的索引改成双字段的覆盖索引

create index index_birthday_and_user_name on user_info(birthday, user_name);

这句SQL语句的执行过程就会变为

通过非聚集索引index_birthday_and_user_name查找birthday等于1991-11-1的叶节点的内容,然而, 叶节点中除了有user_name表主键ID的值以外, user_name字段的值也在里面, 因此不需要通过主键ID值的查找数据行的真实所在, 直接取得叶节点中user_name的值返回即可。 通过这种覆盖索引直接查找的方式, 可以省略不使用覆盖索引查找的后面两个步骤, 大大的提高了查询性能,如下图

 

需要注意的是,为多个字段创建一个索引,比如,在(a,b,c)字段创建一个联合索引,则索引记录会首先按照A字段排序,然后再按照B字段排序,然后再是C字段。联合索引的特点是

1)第一个字段一定是有序的

2)当第一个字段值相等的时候,第二个字段又是有序的

联合索引就像查字典一样,先根据第一个字母查,然后再根据第二个字母查,或者只根据第一个字母查,但是不能跳过第一个字母从第二个字母开始查。这就是所谓的最左前缀原理。

4. B+树

索引的存储结构是B+树,要搞懂B+树,首先要知道什么是二叉查找树和平衡二叉树

二叉查找树:

(1)若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

(2) 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

(3) 任意节点的左、右子树也分别为二叉查找树;

(4) 没有键值相等的节点。

平衡二叉树(高度平衡的二叉查找树):

它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

在增删改的时候会影响平衡树的状态,通过旋转(左旋和右旋)来维系树的平衡,关于树的旋转,可以参考最容易懂得红黑树

不同于顺时针跟逆时针变换这种方式去记忆,上面两个动态图特别方便记忆跟理解:

  左旋就是将节点的右支往左拉,右子节点变成父节点,并把晋升之后多余的左子节点出让给降级节点的右子节点;

  而右旋就是反过来,将节点的左支往右拉,左子节点变成了父节点,并把晋升之后多余的右子节点出让给降级节点的左子节点。

  即左旋就是往左变换,右旋就是往右变换。不管是左旋还是右旋,旋转的目的都是将节点多的一支出让节点给另一个节点少的一支。

举个例子,像上图是否平衡二叉树的图里面,左图在没插入前”19“节点前,该树还是平衡二叉树,但是在插入”19“后,导致了”15“的左右子树失去了”平衡“,所以此时可以将”15“节点进行左旋,让”15“自身把节点出让给”17“作为”17“的左树,使得”17“节点左右子树平衡,而”15“节点没有子树,左右也平衡了。如下图,
 

由于在构建平衡二叉树的时候,当有新节点插入时,都会判断插入后时候平衡,这说明了插入新节点前,都是平衡的,也即高度差绝对值不会超过1。当新节点插入后,有可能会有导致树不平衡,这时候就需要进行调整,而可能出现的情况就有4种,分别称作左左,左右,右左,右右

左左

左左即为在原来平衡的二叉树上,在节点的左子树的左子树下,有新节点插入,导致节点的左右子树的高度差为2,如上即为”10“节点的左子树”7“,的左子树”4“,插入了节点”5“或”3“导致失衡。

​  左左调整其实比较简单,只需要对节点进行右旋即可,如下图,对节点”10“进行右旋,

  注意:如果对左右旋变换还不是很懂或不是很熟练的,可以对照着前面的那两个动图去想象,自己动手变换几次,就明白了。
 

 

MySQL就普遍使用B+Tree实现其索引结构。B-Tree相比,B+Tree有以下不同点:

  • 每个节点的指针上限为2d而不是2d+1;
  • 内节点不存储data,只存储key;
  • 叶子节点不存储指针;

下面是一个简单的B+Tree示意。

由于并不是所有节点都具有相同的域,因此B+Tree中叶节点和内节点一般大小不同。这点与B-Tree不同,虽然B-Tree中不同节点存放的key和指针可能数量不一致,但是每个节点的域和上限是一致的,所以在实现中B-Tree往往对每个节点申请同等大小的空间。一般来说,B+Tree比B-Tree更适合实现外存储索引结构,具体原因与外存储器原理及计算机存取原理有关,将在下面讨论。
          一般在数据库系统或文件系统中使用的B+Tree结构都在经典B+Tree的基础上进行了优化,增加了顺序访问指针。 

如图所示,在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的B+Tree。做这个优化的目的是为了提高区间访问的性能,例如图4中如果要查询key为从18到49的所有数据记录,当找到18后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,极大提到了区间查询效率。

5. MySQL数据库常见两种引擎

https://blog.csdn.net/suifeng3051/article/details/52669644

6. 索引的优化

https://blog.csdn.net/suifeng3051/article/details/52669644

参考

https://zhuanlan.zhihu.com/p/23624390

https://blog.csdn.net/qq_25940921/article/details/82183093

https://blog.csdn.net/suifeng3051/article/details/52669644

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值