数据库-索引的数据结构以及对应存储引擎特性

概述:

对于非常小的表,大部分情况下简单的全表扫描比建立索引更高效。对于中到大型的表,索引就非常有效。但是对于特大型的表,建立和维护索引的代价将会随之增长。这种情况下,需要用到一种技术可以直接区分出需要查询的一组数据,而不是一条一条的记录去匹配。例如可以使用分区技术。
索引是由存储引擎实现的,而不是在服务器层实现的,所以不同的存储引擎具有不同的索引类型和实现。
mysql支持两种索引,一种是B树索引,一种是hash表索引,这两种索引的查询效率都是较高的。

什么是索引:

索引是一种提高查询效率的数据结构(b树或者hash结构)
索引是创建在数据库表中,是对数据库表中的一列或者多列的值进行排序的一个结果,好处就是提高查询效率

索引的分类:

  • 普通索引:没有任何限制,可以给任意字段创建普通索引
  • 唯一性索引:使用unique修饰的字段,值不能重复,主键索引就是唯一性索引。
  • 主键索引: 使用primary key修饰的字段自动创建主键索引
  • 单列索引:在一个字段上创建索引
  • 多列索引:在多个字段上创建索引
  • 全文索引:使用fulltext参数可以设置全文索引,只支持char/varchar/text类型的字段上,常用于数据量较大的字符串类型上。

B-tree

B树:

B-tree树即B树,B即Balanced,平衡的意思。因为B树的原英文名称为B-tree,而国内很多人喜欢把B-tree译作B-树,其实,这是个非常不好的直译,很容易让人产生误解。如人们可能会以为B-树是一种树,而B树又是另一种树。而事实上是,B-tree就是指的B树。

B树(b-树)是一种多路搜索树(不是二叉树):
  • 定义任意非叶子节点最多有M个儿子;且M>2。
  • 根节点的儿子树为[2,M];
  • 除根节点外的非叶子节点的儿子树[M/2,M];
  • 每个结点存放至少M/2-1(取上整) 和至多M-1个关键字; (至少两个关键字)
  • 非叶子结点结点的关键字个数=指向儿子指针个数-1;
  • 非叶子结点的关键字:k[1],k[2]…k[M-1];且k[i]<k[i+1];
  • 非叶子结点的指针:p[1] ,p[2]…p[M];其中p[1] 指向关键字小于K[1]的子树,p[M]指向关键字大于k[M-1]的的子树,其它p[i]指向关键属于(k[i-1],k[i])的子树。
  • 所有叶子结点位于同一层。

M=3:
在这里插入图片描述
b-树的搜索,从根节点开始,对结点内的关键字(有序)序列进行二分查找,如果命中则结束,否则进入查询关键字所属范围的儿子结点;重复以上操作,直到所对应的儿子指针为空,或者已经是叶子结点。

B-树的特性:
  • 关键字集合分布在整颗树中
  • 任何一个关键字出现且只出现在一个结点中
  • 搜索有可能在非叶子结点结束
  • 其搜索性能等价于在关键字全集做一次二分查找
  • 自动层次控制

B+树:

B+树是b-数的变体,也是一种多路搜索树:

其定义基本与B-树相同,一下除外:

  • 非叶子结点的子树指针和关键字个数相同
  • 非叶子结点的子树指针p[i],指向关键字值属于[k[i],k[i+1]]的子树(b-树是开区间的)
  • 为所有叶子结点增加一个链指针
  • 所有关键字都在叶子结点出现。
    M=3:
    在这里插入图片描述
    B+树的搜索与B-树也基本相同,区别是B+树只有达到叶子结点时才命中,其性能也等价于做一次二分查找。
B+树的特性:
  • 所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的。
  • 只能在叶子结点命中
  • 非叶子结点相当于叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层。
  • 更适合文件索引系统
  • 所有的查找时间都是一样的。
B树参考博客:

B树/B-树/B+树/B*树

B-树和B+树的区别:

  1. b-树的每一个节点,存了关键字和对应的数据地址,而b+树的非叶子节点只存放关键字,不存放数据地址。
    因此,b+树的每个非叶子节点存储的关键字是远远多于B-树的,b+树的叶子节点存放关键字和数据,因此从数的高度来说,B+树的高度远小于B-树,使用的磁盘IO次数少,因此查询会更快一点。

  2. b-树由于每个节点都存储关键字和数据,因此离根节点近的数据,查询就快,离根节点远的数据,查询就慢。
    B+树所有的数据都存在叶子节点上,因此在B+树上搜索关键字,找到对应数据的时间是比较平均的,没有快慢之说。

  3. 在b-树上做区间查找,遍历的节点是非常多的;b+树所有叶子节点被连接成了有序链表结构,因此做整表遍历和区间查找是非常容易的。

哈希索引 :

在MYSQL中只有memory存储引擎显式支持索引,这也是memory引擎表的默认索引类型,memory引擎同时也支持B-Tree索引,并且,memory支持非唯一hash索引,如果多个列的hash值相同,索引就会以链表形式存放多个记录指针到同一个hash条目中
哈希索引基于hash表实现,hash表对数据并不排序,因此不适合做区间查找,效率非常低,需要搜索整个hash表结构。

MYSQL存储引擎

MYISAM索引结构:B+树实现

MYISAM引擎使用B+树作为索引结构,叶节点的data域存放的是数据记录地址

扫描二维码关注公众号,回复: 6781525 查看本文章
主键索引:

在这里插入图片描述
MYISAM中,主索引和辅助索引在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key是可以重复的,如果给其它字段创建辅助索引,如下:

辅助索引:

在这里插入图片描述

上面两张图都是按照B+Tree搜索算法搜索索引,如果指定的key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据技记录。

INNODB存储引擎:

mysql INNODB存储引擎,基于b-树(实际上mysql采用的是b+树)的索引结构。
b-树是一种m阶平衡树,叶子结点都在同一层,由于每一个结点存储的数据量比较大,索引整个b-树的层数是非常低的,基本上不超过三层。
由于磁盘上的读取也是按照block块操作的(内存是按page页面操作的),因此b-树的结点大小一般设置为和磁盘块大小一致,这样一个b-树结点就可以通过一次磁盘IO把一个磁盘块的数据全部存储下来,所以当使用b-树存储索引的时候,磁盘IO的操作次数是最少的(MYSQL的读写效率主要将集中在磁盘IO上)

注意:
  • InnoDB支持的hash索引是自适应的,innodb存储引擎会根据表的使用情况自动为表生成hash索引,不能人为干预是否在一张表中生成hash索引。
  • B+树索引并不能找到一个给定键值的具体行。B+树索引能找到的只是被查找数据所在的页。然后数据库通过把页读入内存,再在内存中进行查找,最后得到所要的数据。
主键索引:聚集索引

在这里插入图片描述
innodb存储引擎的主键索引,叶子节点中,索引关键字和数据是一起存放的。

辅助索引:非聚集索引

INNODB的辅助索引,叶子节点存放的是索引关键字和对应的主键关键字。
在这里插入图片描述

辅助索引的B+树,先根据关键字找到对应的主键,再去主键索引树上找到对应的行记录。
从主索引树上可以看到,INNODB的索引关键字和数据都是在一起存放的,体现在磁盘存储上。
如创建一个INNODB存储引擎的user表,在磁盘上值存储两种结构, user.frm(表结构) ,user.idb(索引和数据)

猜你喜欢

转载自blog.csdn.net/Fly_Fly_Zhang/article/details/94323016