索引原理【1】-MySQL

一、什么是索引?

MySQL官方对索引定义:是存储引擎用于快速查找记录的一种数据结构。需要额外开辟空间和数据维护工作。

关于索引的理解,个人更加喜欢将其比喻为字典里面的目录,根据目录来进行查询的速度远大于每一页逐个逐个字排查的速度。

索引主要用于快速找出在某个列中有特定值的行,倘若不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多。如果表中查询的列有一个索引,MySQL能够快速到达一个位置去搜索数据,而不必查找所有数据,那么将会节省很大一部分时间。

我们创建索引的时候是这样的:

create index index_name on table_name(column)

索引中包含了一个表中列的值和它的地址的值,并且这些值存储在一个数据结构中。索引的组织形式有二叉树、哈希、B树、B+树。如果索引存的是一列就叫做单索引,多列就是复合索引。

索引一般以文件形式存在磁盘中(也可以存于内存),存储索引的原理大致概括为以空间换时间。

二、索引能干什么?

假设执行下面的一条sql语句,在一张学生表里面找学号是003的学生:

select name from student where num = "003"

假如一共到100号学生。那么DBMS会生成一个类似指针的东西,从num="001"一直到最后,进行全表扫描。那么为什么到num="003"不停止呢?因为数据库在未添加索引的时候默认执行的是全量搜索,select执行就就是全表扫描,即使扫描主键也一样。

如果我们在num字段上创建了一个索引,假如索引的底层存储结构是二叉树,那么只需要log2(100)次就能查到所需要的数据。因此,建立索引的目的就是加快对表中记录的查找或排序。

当然索引不是万能的,它的缺点有:创建和维护索引需要时间和空间成本,每次增删改索引都需要进行动态维护。

三、索引的分类

主键索引

存储的值不能重复,且不能是null (设定为主键后数据库会自动建立索引,innodb为聚簇索引);

单值索引即一个索引只包含单个列,一个表可以有多个单列索引
唯一索引唯一索引和普通索引类似,主要区别在于,唯一索引限制列的值必须唯一,但允许存在空值(只能有一个)。主键索引不允许有空值。
复合索引多个列构成的索引
全文索引全文索引主要用来查找文本中的关键字,而不是直接与索引中的值进行比较,它更像是一个搜索引擎,而不是简单的where语句的参数匹配。

        目前只有char/vachar/text列上可以创建全文索引,默认Mysql不支持中文全文搜索。Mysql全文搜索只是一个临时方案,对于全文搜索场景,更专业的做法是使用全文搜索引擎,如ElasticSearch。

四、索引的结构是什么?

        索引在起初做设计的时候其实是有一定数据结构选型的,B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引,此外还有Hash索引。B+树中的B代表平衡(balance),而不是二叉(binary),因为B+树是从最早的平衡二叉树演化而来的。在讲B+树之前必须先了解二叉查找树、平衡二叉树(AVL Tree)和多路平衡的查找树(B树),B+树即由这些树逐步优化而来。

二叉树 —— 平衡二叉树 —— B树多路平衡查找树)—— B+树

对于不同的数据结构基础,做了以下的相关总结:

4.1、二叉树

  • 如果左子树不为空,则左子树上所有节点的值均小于根节点的值
  • 如果右子树不为空,则右子树上所有节点的值均大于它的根节点的值
  • 它的左、右子树也分别为二叉排序数(递归定义)

        从图中可以看出,二叉排序树组织数据时,用于查找是比较方便的,因为每次经过一次节点时,最多可以减少一半的可能,不过极端情况会出现所有节点都位于同一侧,直观上看就是一条直线,那么这种查询的效率就比较低了,因此需要对二叉树左右子树的高度进行平衡化处理,于是就有了平衡二叉树(Balenced Binary Tree)。

索引

4.2、平衡二叉树

  • 它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,
  • 它的左子树和右子树都是一颗平衡二叉树。

        所谓“平衡”,说的是这棵树的各个分支的高度是均匀的,它的左子树和右子树的高度之差绝对值小于1,这样就不会出现一条支路特别长的情况。于是,在这样的平衡树中进行查找时,总共比较节点的次数不超过树的高度,这就确保了查询的效率,不论查找、插入、删除操作在平均和最坏的情况下都是O(logn)。

索引

        平衡二叉树是通过旋转来保持平衡的,而旋转是对整棵树的操作,若部分加载到内存中则无法完成旋转操作。其次平衡二叉树的高度相对较大为 log n(底数为2),这样逻辑上很近的节点实际可能非常远,无法很好的利用磁盘预读(局部性原理),所以这类平衡二叉树在数据库和文件系统上的选择就被 pass 了。

空间局部性原理:如果一个存储器的某个位置被访问,那么将它附近的位置也会被访问。

4.3、红黑树(本质也是“平衡”二叉树)

红黑树并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能

4.4、B树(平衡多路查找树)

  • 所有叶节点具有相同的深度,等于树高
  • 所有键值分布在整颗树中(索引值和具体data都在每个节点里);
  • 叶子节点中的数据key从左到右递增排列
  • 树在插入删除新的数据记录会破坏B-Tree的性质,因为在插入删除时,需要对树进行一个分裂、合并、转移等操作以保持B-Tree性质。

        B树,又称平衡多路查找树,也就是说每个节点最多可以开m个叉(m>=2),我们称之为m阶B树。下图为一棵5阶B树

在这里插入图片描述

        B树的查询过程和二叉排序树比较类似,从根节点依次比较每个结点,因为每个节点中的关键字和左右子树都是有序的,所以只要比较节点中的关键字,或者沿着指针就能很快地找到指定的关键字,如果查找失败,则会返回叶子节点,即空指针。

4.5、B+树(B树加强版)

作为B树的加强版,B+树与B树的差异在于

  • 所有的关键字全部存储在叶子节点上,且叶子节点本身根据关键字自小而大顺序连接。
  • 非叶子节点可以看成索引部分,节点中仅含有其子树(根节点)中的最大(或最小)关键字。

因为非叶子节点并不存储 data,所以一般B+树的叶节点和内节点大小不同,而B-树的每个节点大小一般是相同的,为一页。

五、为什么B+树比B树更加适合做数据库的索引

        MySQL中MyIsAM和InnoDB都是采用的B+树结构。不同的是前者是非聚集索引,后者主键是聚集索引,所谓聚集索引是物理地址连续存放的索引,在取区间的时候,查找速度非常快,但同样的,插入的速度也会受到影响而降低。聚集索引的物理位置使用链表来进行存储。

        一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。

1B+树的磁盘读写代价更低

1、B树的节点都存了key和data,

2、B+树只有叶子节点存data,非叶子节点都只是索引值,没有实际的数据,这就使得B+树在一次IO里面,能读出的索引值更多(由于磁盘 IO 数据大小是固定的,在一次 IO 中,单个元素越小,量就越大),从而减少查询时候需要的IO次数!

3、此外每个索引节点能存储更多的索引数据,这样树的高度也就越低,查询效率就越高。

2B+树的查询效率更加稳定

1、由于内部结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

2、B树只要匹配到即可不用管元素位置。

3B+树更加适合在区间查询的情况

B+树叶子节点由双向指针链接,对于范围查找来说,B+树只需遍历叶子节点链表即可,B树却需要重复地中序遍历,在项目中范围查找又很是常见的

六、Hash索引

Hash索引结构:数组+链表

 1、对索引的key进行一次哈希计算,就可以定位数据存储的地址,根据地址直接定位数据的位置

 2、Hash索引仅支持 IN 和 =,但不支持范围查询

 3、Hash冲突问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值