首页 > 数据库 >MySQL十一:索引基本原理

MySQL十一:索引基本原理

时间:2022-08-27 11:44:06浏览次数:104  
标签:存储 基本原理 Tree 索引 InnoDB MySQL 磁盘 节点

转载~

在上一篇《索引基础知识回顾》中提到索引按照存储结构划分有B-Tree索引、Hash索引、B+Tree索引类型,接下来就学习一下这几种索引结构以及在实际存储引擎中的使用情况

一、Hash索引

「Hash底层是由Hash表来实现的,存储引擎都会【对所有的索引列计算一个哈希码】(hash code),哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针,根据键值 <key,value> 存储数据的结构存储<哈希码,指针>,非常适合根据key查找value值,也就是等值查询(单个key查询)」。其结构如下所示:

图片

  • 「Hash索引优缺点」

  • 哈希表按值查询的性能很好,时间复杂度是O(1),在等值查询的时候hash索引要比B+ 树索引更高效,

  • 「Hash索引缺点」

    这也是为什么用树,而不用哈希表的原因

    • 存在 hash 冲突问题
    • 仅能支持【等值查询】,当查询条件为【范围查找(如:in)】就会全表扫描。

Hash索引在MySQL 中Hash结构主要应用在Memory原生的Hash索引 、InnoDB 自适应哈希索引。在《InnoDB的存储结构》已经介绍过自适应哈希索引,这里不再赘述。

二、B-Tree索引

「平衡多路查找树(B-Tree):是为磁盘等外存储设备设计的一种平衡查找树」

「我们知道在InnoDB存储引擎中页是其磁盘管理的最小单位,默认是16KB,而系统一个磁盘块的存储空间没有这么大,因此InnoDB每次申请磁盘空间时都会申请若干地址连续磁盘块来达到页的大小16KB。在查询时如果数据都在一个页中,会减少磁盘I/O次数,提高查询效率。」

「B-Tree结构的数据可以让系统高效的找到数据所在的磁盘块」。它每个节点根据实际情况可以包含大量的关键字信息和分支,下图为一个3阶的B-Tree:

图片

由上图中可以看出B-Tree有如下「特征」

  • 每个节点占用一个磁盘块的磁盘空间

  • 一个节点上有两个升序排序的关键字和三个指向子树根节点的指针

    • 指针存储的是子节点所在磁盘块的地址
    • 两个关键字划分成的三个范围域对应三个指针指向的子树的数据的范围域

模拟查找关键字29的过程:

  • 根据根节点找到磁盘块1,读入内存。【磁盘I/O操作第1次】

    关键字为17和35,P1指针指向的子树的数据范围为小于17,P2指针指向的子树的数据范围为17~35,P3指针指向的子树的数据范围为大于35。

  • 比较关键字29在区间(17,35),找到磁盘块1的指针P2。

  • 根据P2指针找到磁盘块3,读入内存。【磁盘I/O操作第2次】

  • 比较关键字29在区间(26,30),找到磁盘块3的指针P2。

  • 根据P2指针找到磁盘块8,读入内存。【磁盘I/O操作第3次】

  • 在磁盘块8中的关键字列表中找到关键字29。

通过以上过程,我们查找29,只需要三次IO,「而3阶的B-Tree可以容纳百万级数据,这对查询性能的提升是巨大的」。如果没有索引,每个数据项都要发生一次IO,总共需要百万次的IO,显然成本非常非常高。

三、B+Tree索引

「B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构,InnoDB存储引擎就是用B+Tree实现其索引结构」

在上述中提到数据页的存储空间默认是16KB,而B-Tree结构图中可以看到每个节点中不仅包含数据的key值,还有data值。当数据较大时,一个节点(即一个页)能存储的key的数量就会很小,导致B-Tree的深度变大,增大查询时的磁盘I/O次数,进而影响查询效率。

对此,「B+Tree进行了优化,将所有数据都是按照键值大小顺序存放在同一层的叶子节点上,非叶子节点上只存储key值,以此增大每个节点存储的key值数量,降低B+Tree的高度」。下图为一个3阶的B+Tree:

图片

通过示意图可以看出「B+Tree不仅仅将数据存放在叶子结点,而且所有叶子节点(数据节点)之间都有一个链指针,从而方便叶子节点的范围遍历」。特征如下:

  • 所有关键字都「有序的」出现在叶子结点的链表中(稠密索引)。
  • 非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层。
  • 每一个叶子节点都包含指向下一个叶子节点的指针,从而方便叶子节点的范围遍历。

四、MySQL索引实现

「MySQL中索引属于存储引擎级别的概念,MyISAM和InnoDB都是使用B+Tree作为索引结构,但是不同存储引擎对索引的实现方式不同」

4.1 MyISAM索引实现

《存储引擎》一文中介绍到MyISAM针对每个表有两个文件:「一个.frm表结构文件,一个MYD表数据文件,一个.MYI索引文件」。数据和索引是分开存储的。

「MyISAM使用B+Tree作为索引结构时,.MYI索引文件的叶节点的data域存放的是数据记录的地址」

图片

按照示意图:MyISAM在索引检索时首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。

「在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复」图片

4.2 InnoDB索引实现

《存储引擎》一文中介绍到InnoDB针对每个表有两个文件:「一个.frm表结构文件,一个.ibd数据文件」,数据和索引是一起存储的,定位到了数据也就找到了数据。

4.2.1聚簇索引(聚集索引)

「InnoDB的聚簇索引就是按照主键顺序构建 B+Tree结构。叶子节点data域存储了完整的数据记录,行记录和主键值紧凑地存储在一起。即 InnoDB 的主键索引就是数据表本身,它按主键顺序存放了整张表的数据,占用的空间就是整个表数据量的大小。」

  • InnoDB的表要求必须要有聚簇索引:

    • 如果表定义了主键,则主键索引就是聚簇索引
    • 如果表没有定义主键,则第一个非空unique列作为聚簇索引
    • 都没有InnoDB会从建一个隐藏的row-id作为聚簇索引
  • 聚簇索引示意图:

图片

4.2.2辅助索引(二级索引)

「在InnoDB中,主索引和辅助索引(Secondary key)的Data域存储是不同的」,这与MyISAM是不同的。

  • 「但在 B+Tree 的叶子节点中只存了【索引列和主键】的信息。二级索引占用的空间会比聚簇索引小很多, 通常创建辅助索引就是为了提升查询效率。一个表InnoDB只能创建一个聚簇索引,但可以创建多个辅助索引」

图片

如示意图所示,辅助索引索引中data域中存储的是主键,所以辅助索引一般需要两次查找才能查到数据:

  • 「第一次通过辅助索引找到主键列的值」
  • 「第二次通过主键列的值在聚簇索引中查找数据」

图片

标签:存储,基本原理,Tree,索引,InnoDB,MySQL,磁盘,节点
From: https://www.cnblogs.com/yunlongn/p/16630239.html

相关文章

  • 记一次血淋淋的MySQL崩溃修复案例
    摘要:今天给大家带来一篇MySQL数据库崩溃的修复案例本文分享自华为云社区《记一次MySQL崩溃修复案例,再也不用删库跑路了》,作者:冰河。问题描述研究MySQL源代码,调试并压......
  • MySQL MGR新增成员-xtrabackup
    4.6.在组复制中使用备份数据恢复失败的成员或增加新成员由于官方手册中使用了企业版的mysqlbackup做演示步骤,以下本节内容采用开源的percona-xtrabackup8.0.7版本演示对......
  • MySQL second_behind_master计算方式
    对于主从库主机时间不一致的情况,在I/O线程第一次启动时,会计算主从之间的主机时间差,在后续计算复制延迟时,会把这个时间差减掉,这样就可以保证正确获取到复制延迟时间,但是该时......
  • mysql的date类型:没有时分秒
    mysql的date类型:没有时分秒几种类型比较如下:日期时间类型占用空间日期格式最小值最大值零值表示DATETIME8bytesYYYY-MM-DDHH:MM:SS1000-01-0100:00:0......
  • Mysql---多表查询
    《需求》  比如说:我们要显示一系列信息,但是这些信息并不是在同一个表上的,可能在多个表上这个时候就要展示多张表的内容如:    如果我直接这样会显示什么呢......
  • mysql group by问题之ONLY_FULL_GROUP_BY特性
    背景:执行 groupby语句时,没有办法select*出来所有的字段,以至于再对中间某些字段计算时无法推断,影响结果,具体如下:  报错内容Expression#1ofSELECTlistisn......
  • mysql 开启root远程连接_mysql开启root用户可远程登录方法
    mysql开启root远程连接_mysql开启root用户可远程登录方法要设置我们的mysql服务器支持远程登录方法有很多但也相当的简单,下面来看看开启远程登录的方法吧。开启MySQL......
  • mysql查询出所有重复的记录
    假如我们有如下一张数据表(很简单,只是举例而已),表名为student。现在我们要取出其中重复记录。重复是以name相同为判定标准。shortnameageheightweightprovinceunivers......
  • 【MySql】Update批量更新与批量更新多条记录的不同值实现方法
    批量更新mysql更新语句很简单,更新一条数据的某个字段,一般这样写:UPDATEmytableSETmyfield='value'WHEREother_field='other_value';如果更新同一字段为同一个......
  • MySQL加快批量更新 UPDATE优化
    MySQL加快批量更新UPDATE优化-小昌君-博客园 https://www.cnblogs.com/liaokaichang/p/7099564.html如果是更新为同样的内容,没啥难度,直接在where里面下功夫就好了,......