MySQL索引的数据结构

这篇具有很好参考价值的文章主要介绍了MySQL索引的数据结构。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、索引的简介

1、索引的概念

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。
mysql索引数据结构,数据库,MySQL,索引
mysql索引数据结构,数据库,MySQL,索引

索引的本质:索引是数据结构。你可以简单理解为“排好序的快速查找数据结构”,满足特定查找算法。这些数据结构以某种方式指向数据, 这样就可以在这些数据结构的基础上实现 高级查找算法

2、索引的优点

  • 类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本这也是创建索引最主要的原因
  • 通过创建唯一索引,可以保证数据库表中每一行 数据的唯一性
  • 在实现数据的参考完整性方面,可以 加速表和表之间的连接。换句话说,对于有依赖关系的子表和父表联合查询时,可以提高查询速度
  • 在使用分组和排序子句进行数据查询时,可以显著 减少查询中分组和排序的时间 ,降低了CPU的消耗。

3、索引的缺点

  • 创建索引和维护索引要 耗费时间 ,并且随着数据量的增加,所耗费的时间也会增加。
  • 索引需要占 磁盘空间 ,除了数据表占数据空间之外,每一个索引还要占一定的物理空间, 存储在磁盘上 ,如果有大量的索引,索引文件就可能比数据文件更快达到最大文件尺寸。
  • 虽然索引大大提高了查询速度,同时却会 降低更新表的速度 。当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度

二、索引的代价

索引是个好东西,可不能乱建,它在空间和时间上都会有消耗:

1、空间上的代价

每建立一个索引都要为它建立一棵B+树,每一棵B+树的每一个节点都是一个数据页,一个页默认会占用 16KB 的存储空间,一棵很大的B+树由许多数据页组成,那就是很大的一片存储空间。
时间上的代价

2、时间上的代价

每次对表中的数据进行 增、删、改 操作时,都需要去修改各个B+树索引。而且我们讲过,B+树每层节点都是按照索引列的值 从小到大的顺序排序 而组成了 双向链表 。不论是叶子节点中的记录,还是内节点中的记录(也就是不论是用户记录还是目录项记录)都是按照索引列的值从小到大的顺序而形成了一个单向链表。而增、删、改操作可能会对节点和记录的排序造成破坏,所以存储引擎需要额外的时间进行一些 记录移位 , 页面分裂 、 页面回收 等操作来维护好节点和记录的排序。如果我们建了许多索引,每个索引对应的B+树都要进行相关的维护操作,会给性能拖后腿。

三、InnoDB中索引的推演

1、设计索引

可以联想操作系统中的页表机制,一层套一层(通过目录项找页,当目录项中过多时,我们会继续设置目录项去找目录项…),最后形成B+树的形式

1)以c1创建索引(因为c1是主键)

mysql> CREATE TABLE index_demo(
 ->   c1 INT,
 ->   c2 INT,
 ->   c3 CHAR(1),
 ->   PRIMARY KEY(c1)
 -> ) ROW_FORMAT = Compact;

2)数据库中一条记录的格式

mysql索引数据结构,数据库,MySQL,索引

  • record_type :记录头信息的一项属性,表示记录的类型, 0 表示普通记录、 2 表示最小记录、 3 表示最大记录、 1 是目录项。
  • next_record:记录头信息的一项属性,表示下一条地址相对于本条记录的地址偏移量,我们用箭头来表明下一条记录是谁。
  • 各个列的值 :这里只记录在 index_demo 表中的三个列,分别是 c1 、 c2 和 c3 。
  • 其他信息 :除了上述3种信息以外的所有信息,包括其他隐藏列的值以及记录的额外信息。

3)将记录放在数据页中

数据库中的数据在磁盘中是以数据页的形式进行存储的,每一页中的每一行叫做记录

页内的数据是按照主键值进行排序的,所以页内数据我们是可以通过二分法去查找的。
mysql索引数据结构,数据库,MySQL,索引

4)当页过多时,需要为页设置目录项

mysql索引数据结构,数据库,MySQL,索引

5)当目录项过多时,我们需要为目录项设置目录项

mysql索引数据结构,数据库,MySQL,索引

6)最后形成B+树的形式

mysql索引数据结构,数据库,MySQL,索引

一个B+树的节点其实可以分成好多层,规定最下边的那层,也就是存放我们用户记录的那层为第 0层,之后依次往上加。之前我们做了一个非常极端的假设:存放用户记录的页最多存放3条记录 ,存放目录项记录的页 最多存放4条记录 。其实真实环境中一个页存放的记录数量是非常大的(MySQL中一页的大小为16KB),假设所有存放用户记录的叶子节点代表的数据页可以存放100条用户记录,所有存放目录项记录的内节点代表的数据页可以存放1000条目录项记录 ,那么:

  • 如果B+树只有1层,也就是只有1个用于存放用户记录的节点,最多能存放 100 条记录。
  • 如果B+树有2层,最多能存放 1000×100=10,0000 条记录。
  • 如果B+树有3层,最多能存放 1000×1000×100=1,0000,0000 条记录。
  • 如果B+树有4层,最多能存放 1000×1000×1000×100=1000,0000,0000 条记录。相当多的记录!!!

因此,面试中问,为什么MySQL的B+树最多只有四层?
因为四层就已经能够存储相当量的数据了,足够我们使用,毕竟四层可以存储100000000000 条记录了。

那怎么去查找我们所需要的的记录了?
通过主键值去查找某条记录最多只需要做4个页面内的查找(查找3个目录项页和一个用户记录页),又因为在每个页面内有所谓的 Page Directory(页目录),所以在页面内也可以通过 二分法 实现快速定位记录

2、常见索引概念

2.1、聚簇索引

1、特点

上面举的例子是基于主键进行排序的,所以是聚簇索引!

  • 使用记录主键值的大小进行记录和页的排序,这包括三个方面的含义:
    • 页内 的记录是按照主键的大小顺序排成一个 单向链表
    • 各个存放 用户记录的页 也是根据页中用户记录的主键大小顺序排成一个 双向链表
    • 存放目录项记录的页 分为不同的层次,在同一层次中的页也是根据页中目录项记录的主键大小顺序排成一个 双向链表
  • B+树的 叶子节点 存储的是完整的用户记录
    所谓完整的用户记录,就是指这个记录中存储了所有列的值(包括隐藏列)

2、优点

  • 数据访问更快 ,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快
  • 聚簇索引对于主键的 排序查找范围查找 速度非常快
  • 按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多个数据块中提取数据,所以 节省了大量的io操作

3、缺点

  • 插入速度严重依赖于插入顺序 ,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
  • 更新主键的代价很高 ,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新
  • 二级索引访问需要两次索引查找 ,第一次找到主键值,第二次根据主键值找到行数据

2.2、二级索引(又叫辅助索引、非聚簇索引)

二级索引我们并不是将主键作为索引,而是用非主键进行索引。每一行的记录包括非主键的索引和主键。
mysql索引数据结构,数据库,MySQL,索引
因此我们利用二级索引去查找某个完整的记录,需要两步操作,第一步,通过二级索引去查找主键,第二步,通过聚簇索引去查找记录。
这就是回表操作,所以查找一条记录我们需要查找两棵B+索引树!

面试问题,为什么需要一次回表操作了?直接把完整的用户记录放到叶子节点不OK吗?
因为在数据库中不会只设置一个二级索引,如果每个二级索引的叶子结点都放置完整的用户数据(每个用户的数据可能有几百万个),会极大的加大存储空间的开销

mysql索引数据结构,数据库,MySQL,索引

2.3、联合索引

我们也可以同时以多个列的大小作为排序规则,也就是同时为多个列建立索引,比方说我们想让B+树按照 c2和c3列 的大小进行排序,这个包含两层含义:

  • 先把各个记录和页按照c2列进行排序。
  • 在记录的c2列相同的情况下,采用c3列进行排序

注意一点,以c2和c3列的大小为排序规则建立的B+树称为 联合索引 本质上也是一个二级索引。它的意思与分别为c2和c3列分别建立索引的表述是不同的,不同点如下:

  • 建立 联合索引 只会建立如上图一样的1棵B+树。
  • 为c2和c3列分别建立索引会分别以c2和c3列的大小为排序规则建立2棵B+树。

三、索引的数据结构

1、全表遍历

复杂度是O(n)的,效率很差

2、Hash结构

Hash结构的效率是很高的,时间复杂度可以为O(1)

那为什么Hash结构的效率这么搞,那为什么索引的数据结构设计成树形了?有四点原因

mysql索引数据结构,数据库,MySQL,索引

Hash索引适用存储引擎如表所示:

mysql索引数据结构,数据库,MySQL,索引

虽然在InnoDB存储引擎中,不支持Hash索引,但是却提供了自适应Hash索引(Adaptive Hash Index)。

那什么情况下使用自适应Hash索引了?

如果某个数据经常被访问,当满足一定条件的时候,就会将这个数据页的地址存放到hash表中,这样在下次查询的时候,就可以找到这个页面所在的位置。这样B+树也具备了Hash索引的优点。

mysql索引数据结构,数据库,MySQL,索引
采用自适应 Hash 索引目的是方便根据 SQL 的查询条件加速定位到叶子节点,特别是当 B+ 树比较深的时候,通过自适应 Hash 索引可以明显提高数据的检索效率。

我们可以通过innodb_adaptive_hash_index变量来查看是否开启了自适应 Hash,比如:

show variables like '%adaptive_hash_index';

mysql索引数据结构,数据库,MySQL,索引

3、二插搜索树

二插搜索树在某种情况下,时间复杂度会变成O(n)
mysql索引数据结构,数据库,MySQL,索引
为了提高查询效率,就需要 减少磁盘IO数 。为了减少磁盘IO的次数,就需要尽量 降低树的高度 ,需要把原来“瘦高”的树结构变的“矮胖”,树的每层的分叉越多越好。

4、AVL树

mysql索引数据结构,数据库,MySQL,索引

5、 B树

mysql索引数据结构,数据库,MySQL,索引
一个 M 阶的 B 树(M>2)有以下的特性:

(1)根节点的儿子数的范围是 [2,M]。
(2)每个中间节点包含 k-1 个关键字和 k 个孩子,孩子的数量 = 关键字的数量 +1,k 的取值范围为[ceil(M/2), M]。
(3)叶子节点包括 k-1 个关键字(叶子节点没有孩子),k 的取值范围为 [ceil(M/2), M]。
(4)假设中间节点节点的关键字为:Key[1], Key[2], …, Key[k-1],且关键字按照升序排序,即 Key[i]
<Key[i+1]。此时 k-1 个关键字相当于划分了 k 个范围,也就是对应着 k 个指针,即为:P[1], P[2], >…,P[k],其中 P[1] 指向关键字小于 Key[1] 的子树,P[i] 指向关键字属于 (Key[i-1], Key[i]) 的子树,P[k]>指向关键字大于 Key[k-1] 的子树。
(4)所有叶子节点位于同一层。

上面那张图所表示的 B 树就是一棵 3 阶的 B 树。我们可以看下磁盘块 2,里面的关键字为(8,12),它有 3 个孩子 (3,5),(9,10) 和 (13,15),你能看到 (3,5) 小于 8,(9,10) 在 8 和 12 之间,而 (13,15)大于 12,刚好符合刚才我们给出的特征。

然后我们来看下如何用 B 树进行查找。假设我们想要 查找的关键字是 9 ,那么步骤可以分为以下几步

  • (1)我们与根节点的关键字 (17,35)进行比较,9 小于 17 那么得到指针 P1;
  • (2)按照指针 P1 找到磁盘块 2,关键字为(8,12),因为 9 在 8 和 12 之间,所以我们得到指针 P2;
  • (3)按照指针 P2 找到磁盘块 6,关键字为(9,10),然后我们找到了关键字 9。

你能看出来在 B 树的搜索过程中,我们比较的次数并不少,但如果把数据读取出来然后在内存中进行比较,这个时间就是可以忽略不计的。而读取磁盘块本身需要进行 I/O 操作,消耗的时间比在内存中进行比较所需要的时间要多,是数据查找用时的重要因素。 B 树相比于平衡二叉树来说磁盘 I/O 操作要少,在数据查询中比平衡二叉树效率要高。所以 只要树的高度足够低,IO次数足够少,就可以提高查询性能

6、B+树

1、B+树和B树的差异

  • B+树有 k 个孩子的节点就有 k 个关键字。也就是孩子数量 = 关键字数,而 B 树中,孩子数量 = 关键字数+1。
  • B+树中,非叶子节点的关键字也会同时存在在子节点中,并且是在子节点中所有关键字的最大(或最小)。
  • B+树中,非叶子节点仅用于索引,不保存数据记录,跟记录有关的信息都放在叶子节点中。而 B 树中, 非叶子节点既保存索引,也保存数据记录 。
  • 所有关键字都在叶子节点出现,叶子节点构成一个有序链表,而且叶子节点本身按照关键字的大小从小到大顺序链接。

2、B+树就比B树好吗?

B 树和 B+ 树都可以作为索引的数据结构,在 MySQL 中采用的是 B+ 树。但B树和B+树各有自己的应用场景,不能说B+树完全比B树好,反之亦然。

3 、思考题:为了减少IO,索引树会一次性加载吗?

不会,因为索引会占用空间,大量的索引可能会超出1g多的大小,所以不会一次性加载

4、思考题:B+树的存储能力如何?为何说一般查找行记录,最多只需1~3次磁盘IO

储存能力很强,倘若一开始的根页可以存放100条数据条目,那如果页目录可以存放1000条,那二级存放的量就1001000,三级就是10010001000,4级就是100100010001000,那为什么最多只需要加载最大3次呢,因为根页的数据在一开始已经加载了所有无需加载,那么就算最大加载4级,那也就需要加载最大3次

5、思考题:为什么说B+树比B-树更适合实际应用中操作系统的文件索引和数据库索引?

因为B+树查询更为稳定,且适合范围的快速查找

6、思考题:Hash 索引与 B+ 树索引的区别

HASH索引的范围查找效率比B+树索引效率低很多,且不支持联合索引

7、思考题:Hash 索引与 B+ 树索引是在建索引的时候手动指定的吗?

不是的,是一开始我们创建表的时候,每次插入数据,他背后都会去维护对应索引,如果又新加的二级索引才会再创建索引

7、R树

R-Tree在MySQL很少使用,仅支持 geometry数据类型 ,支持该类型的存储引擎只有myisam、bdb、innodb、ndb、archive几种。

举个R树在现实领域中能够解决的例子:查找20英里以内所有的餐厅。如果没有R树你会怎么解决?一般情况下我们会把餐厅的坐标(x,y)分为两个字段存放在数据库中,一个字段记录经度,另一个字段记录纬度。这样的话我们就需要遍历所有的餐厅获取其位置信息,然后计算是否满足要求。如果一个地区有100家餐厅的话,我们就要进行100次位置计算操作了,如果应用到谷歌、百度地图这种超大数据库中,这种方法便必定不可行了。R树就很好的解决了这种高维空间搜索问题。它把B树的思想很好的扩展到了多维空间,采用了B树分割空间的思想,并在添加、删除操作时采用合并、分解结点的方法,保证树的平衡性。因此,R树就是一棵用来存储高维数据的平衡树 。相对于B-Tree,R-Tree的优势在于范围查找

mysql索引数据结构,数据库,MySQL,索引文章来源地址https://www.toymoban.com/news/detail-621507.html

四、索引的适用和不适用场景

1、适用场景

  • 主键自动建立唯一索引
  • 频繁作为查询的条件的字段应该创建索引
  • 查询中与其他表关联的字段
  • 频繁更新的字段不适合创建索引
  • 查询中排序的字段,排序字段若通过索引去访问将大大提高排序的速度
  • 查询中统计或者分组字段

2、不适用场景

  • Where条件里用不到的字段不创建索引
  • 表记录太少
  • 经常增删改的表
  • 数据重复且分布平均的表字段

到了这里,关于MySQL索引的数据结构的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mysql数据库结构优化汇总

         设计表以最大限度地减少其在磁盘上的空间。这可以减少写入磁盘和从磁盘读取的数据量,从而带来巨大的改进。较小的表通常需要较少的主内存,而它们的内容在查询执行过程中被主动处理。表数据的任何空间减少也会导致更小的索引可以更快地处理。 尽可能使用最

    2024年02月07日
    浏览(46)
  • Mysql不同数据库之间表结构同步

    开发环境的Mysql表结构做了修改,要同步到其他环境数据库中使用数据库管理工具JookDB的表结构同步功能就很方便。虽然Navicat也有这个功能但是有免费的当然是用免费的。 用JookDB添加数据库后在数据库节点上右键选择“同步结构”即可开始表结构同步。 1.选择结构同步的源库

    2024年02月05日
    浏览(50)
  • 【数据库——MySQL(实战项目1)】(1)图书借阅系统——数据库结构设计

    经过前期的学习,我们已经掌握数据库基础操作,因此是时候来做一个实战项目了—— 图书借阅系统 。对于图书借阅系统,相信大家不难想到至少需要 3 张表,分别是: 借阅人表 , 图书表 和 借阅信息表 (当然不限于这些表,大家可以根据自己的想法创建其它表)。 那么

    2024年02月03日
    浏览(65)
  • MySql数据库的初步安装与数据表结构数据管理

    目录 一、数据库的相关了解 1)数据库的概念  数据(Data) 表 数据库系统 2)数据库系统发展史 第一代数据库 第二代数据库 第三代数据库 当今主流数据库介绍 2)数据库的分类  关系数据库 非关系型数据库 非关系型数据库的优点 二、mysql的yum安装与源码编译安装   1)源

    2024年02月08日
    浏览(361)
  • MySQL数据库精选(从入门使用到底层结构)

    DDL: 数据定义语言,用来定义数据库对象(数据库、表、字段) DML: 数据操作语言,用来对数据库表中的数据进行增删改 DQL: 数据查询语言,用来查询数据库中表的记录 DCL: 数据控制语言,用来创建数据库用户、控制数据库的控制权限 数据定义语言 数据库操作 查询所有数据

    2024年02月19日
    浏览(49)
  • mysql从入门到放弃之数据库体系结构与管理

    第一篇文章中主要学习了mysql二进制的基本安装及数据库初始化等操作,本篇文章主要了解mysql的体系结构和管理,例如: mysql的实例组成、逻辑存储结构、物理存储结构等方面展开学习 提示:以下是本篇文章正文内容,下面案例可供参考 3.1、mysqld守护进程结构 3.2、 引入sql语句

    2024年01月21日
    浏览(48)
  • MySQL数据库---库基本操作 以及 表结构的操作(DDL)

    目录 前言 一.数据库的操作 1.1显示当前数据库 1.2创建数据库 1.3使用数据库  1.4删除数据库  二.数据类型 2.1数值类型 2.2字符串类型 2.3日期类型 三.数据表的操作  3.1 创建表结构。  3.2查看数据库中拥有的数据表  3.3查看指定的表结构   3.4修改表结构   3.5删除表结构  

    2024年02月09日
    浏览(65)
  • MySQL的数据结构:数据库(Database)、表(Table)、记录(Record)和字段(Field)

    MySQL的数据结构可以看作是一个层次化的组织方式,从最高的层次到最低的层次分别是:数据库(Database)、表(Table)、记录(Record,也就是数据行)和字段(Field,也就是数据列)。 数据库(Database) : 数据库是最高层次的存储结构,它可以包含多个表、视图、存储过程、

    2024年02月21日
    浏览(56)
  • MySQL高级第十一篇:数据库调优策略(定位-调优-结构)

    1.尽可能节省系统资源,以便系统可以提供更大负荷的服务。 (吞吐量更大) 2.合理的结构设计和参数调整,以提高用户操作响应的速度。 (响应速度更快) 3.减少系统的瓶颈,提高MySQL数据库整体的性能。 用户是我们的服务对象,因此他们的反馈是最直接的。虽然他们不会

    2023年04月10日
    浏览(51)
  • 数据库索引结构(1)概念

    MySQL学习笔记-主键索引和二级索引_mysql中主键索引和二级索引的区别_爱因诗贤的博客-CSDN博客 MYSQL-主键索引与二级索引_mysql二级索引存在哪个文件_青苔小榭的博客-CSDN博客       采用主键索引的好处:如果元素的位置发生修改,那么查找的复杂度没有变化 因为只是根据主键

    2024年02月06日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包