【mysql】聚簇索引和非聚簇索引(B树和B+树)

这篇具有很好参考价值的文章主要介绍了【mysql】聚簇索引和非聚簇索引(B树和B+树)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

  • 博主简介:想进大厂的打工人
  • 博主主页:@xyk:
  • 所属专栏: mysql

目录

一、索引分类

二、索引的数据结构

2.1 B树:改造二叉树

2.2 B+树:改造B树

三、Mysql索引实现—InnoDB引擎

3.1 主键索引(聚簇索引)

3.2 辅助索引(非聚簇索引)

3.3 避免回表

3.4 覆盖索引


一、索引分类

索引一般可以分为以下几类:

主键索引:主键索引是一种特殊的索引类型,它是用于唯一标识每一行数据的索引,每个表只能有一个主键索引,索引列中的值必须是唯一的,不允许有空值。

复合索引:复合索引也叫多列索引或联合索引,它是包含多个列的索引类型,能够加速多列查询和排序操作。需要遵循最左前缀匹配原则(最左匹配原则)

普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值。

唯一索引:唯一索引是用来保证列的唯一性的索引,一个表可以有多个唯一索引。比如说,因为人有可能同名,所以同一个姓名在同一个“员工个人资料”数据表里可能出现两次或更多次。索引列中的值必须是唯一的,但是允许为空值。

全文索引:全文索引是一种用于全文搜索的索引类型,能够对文本数据进行快速的模糊搜索和关键字搜索。只能在文本类型CHAR,VARCHAR,TEXT类型字段上创建全文索引。

哈希索引:哈希索引是基于哈希表实现的索引类型,能够对等值查询进行高效的处理,但不支持范围查询和排序,MySQL 中 Memory 引擎中支持哈希索引。

二、索引的数据结构

Hash表

Hash表,在Java中的HashMap,TreeMap就是Hash表结构,以键值对的方式存储数据。我们使用Hash表存储表数据Key可以存储索引列,Value可以存储行记录或者行磁盘地址。Hash表在等值查询时效率很高,时间复杂度为O(1);但是不支持范围快速查找,范围查找时还是只能通过扫描全表方式。

2.1 B树:改造二叉树

MySQL的数据是存储在磁盘文件中的,查询处理数据时,需要先把磁盘中的数据加载到内存中,磁盘IO操作非常耗时,所以我们优化的重点就是尽量减少磁盘IO操作。访问二叉树的每个结点就会发生一次IO,如果想要减少IO操作,就需要降低树的高度。

假如key为bigint=8字节,每个节点有两个指针,每个指针为4个字节,一个节点占用的空间16个字节(8+4*2=16)。

因为在MySQL的InnoDB存储引擎一次IO会读取的一页(默认一页16K)的数据量,而二叉树一次IO有效数据量只有16字节,空间利用率极低。为了最大化利用一次IO空间,一个简单的想法是在每个节点存储多个元素,在每个节点尽可能多的存储数据。每个节点可以存储1000个索引(16k/16=1000),这样就将二叉树改造成了多叉树,通过增加树的叉树,将树从高瘦变为矮胖。构建1百万条数据,树的高度只需要2层就可以(1000*1000=1百万),也就是说只需要2次磁盘IO就可以查询到数据。磁盘IO次数变少了,查询数据的效率也就提高了。

这种数据结构我们称为B树,B树是一种多叉平衡查找树,如下图主要特点:

  1. B树的节点中存储着多个元素,每个内节点有多个分叉。
  2. 节点中的元素包含键值和数据,节点中的键值从大到小排列。也就是说,在所有的节点都储存数据。
  3. 父节点当中的元素不会出现在子节点中。
  4. 所有的叶子结点都位于同一层,叶节点具有相同的深度,叶节点之间没有指针连接。

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

 举个例子:

假如我们查询值等于10的数据。查询路径磁盘块1->磁盘块2->磁盘块5。

第一次磁盘IO:将磁盘块1加载到内存中,在内存中从头遍历比较,10<15,走左路,到磁盘寻址磁盘块2。

第二次磁盘IO:将磁盘块2加载到内存中,在内存中从头遍历比较,7<10,到磁盘中寻址定位到磁盘块5。

第三次磁盘IO:将磁盘块5加载到内存中,在内存中从头遍历比较,10=10,找到10,取出data,如果data存储的行记录,取出data,查询结束。如果存储的是磁盘地址,还需要根据磁盘地址到磁盘中取出数据,查询终止。

相比二叉平衡查找树,在整个查找过程中,虽然数据的比较次数并没有明显减少,但是磁盘IO次数会大大减少。同时,由于我们的比较是在内存中进行的,比较的耗时可以忽略不计。B树的高度一般2至3层就能满足大部分的应用场景,所以使用B树构建索引可以很好的提升查询的效率。

过程如图:

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

看到这里你一定觉得B树很理想了,但是B树不支持范围查询的快速查找,如果我们想查询15-30之间的数据,查到15之后,我们还要返回根节点重新遍历查找下一个数据,直到全部遍历找到。

如果data存储的是行记录,行的大小随着列数的增多,所占空间会变大。这时,一个页中可存储的数据量就会变少,树相应就会变高,磁盘IO次数就会变大。

2.2 B+树:改造B树

B+树,作为B树的升级版,在B树基础上,MySQL在B树的基础上继续改造,使用B+树构建索引。B+树和B树最主要的区别在于非叶子节点是否存储数据的问题

  • B树:非叶子节点和叶子节点都会存储数据。
  • B+树:只有叶子节点才会存储数据,非叶子节点至存储键值。叶子节点之间使用双向指针连接,最底层的叶子节点形成了一个双向有序链表。

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

范围查询:
假如我们想要查找9和26之间的数据。查找路径是磁盘块1->磁盘块2->磁盘块6->磁盘块7。

  1. 首先查找值等于9的数据,将值等于9的数据缓存到结果集。这一步和前面等值查询流程一样,发生了三次磁盘IO。
  2. 查找到15之后,底层的叶子节点是一个有序列表,我们从磁盘块6,键值9开始向后遍历筛选所有符合筛选条件的数据。
  3. 第四次磁盘IO:根据磁盘6后继指针到磁盘中寻址定位到磁盘块7,将磁盘7加载到内存中,在内存中从头遍历比较,9<25<26,9<26<=26,将data缓存到结果集。
  4. 主键具备唯一性(后面不会有<=26的数据),不需再向后查找,查询终止。将结果集返回给用户。

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

  1. B+树的节点中可存N个key,N个key划分出N个区间,树的高度是相对矮的。
  2. 所有父节点都会重复出现在子节点中,从左到右依次递增
  3. 非叶子结点只起索引作用, 叶子结点包含信息。
  4. 非叶子结点可能在内存中缓存
  5. 所有的叶子结点都位于最后一层,叶节点之间首尾连接,所有key值都在子节点中存在,且最大为key

MySQL的索引就采用了B+树的数据结构。

三、Mysql索引实现—InnoDB引擎

3.1 主键索引(聚簇索引)

聚集索引:指索引项的排序方式和表中数据记录排序方式一致的索引。聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。

每个InnoDB表都有一个聚簇索引 ,聚簇索引使用B+树构建,叶子节点存储的数据是整行记录。一般情况下,聚簇索引等同于主键索引,当一个表没有创建主键索引时,InnoDB会自动创建一个ROWID字段来构建聚簇索引。

除聚簇索引之外的所有索引都称为辅助索引。在中InnoDB,辅助索引中的叶子节点存储的数据是该行的主键值。在检索时,InnoDB使用此主键值在聚簇索引中搜索行记录。

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

select * from user_innodb where id = 28;

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

  1. 先在主键树中从根节点开始检索,将根节点加载到内存,比较28<75,走左路。(1次磁盘IO)
  2. 将左子树节点加载到内存中,比较16<28<47,向下检索。(1次磁盘IO)
  3. 检索到叶节点,将节点加载到内存中遍历,比较16<28,18<28,28=28。查找到值等于28的索引项,直接可以获取整行数据。将改记录返回给客户端。(1次磁盘IO)
     

磁盘IO数量:3次。

3.2 辅助索引(非聚簇索引)

非聚集索引: 索引顺序与物理存储顺序不同

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

除聚簇索引之外的所有索引都称为辅助索引,InnoDB的辅助索引只会存储主键值而非磁盘地址.

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

使用辅助索引需要检索两遍索引:首先检索辅助索引获得主键,然后使用主键到主索引中检索获得记录。

select * from t_user_innodb where age=19;

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

根据在辅助索引树中获取的主键id,到主键索引树检索数据的过程称为回表查询。

磁盘IO数:辅助索引3次+获取记录回表3次

3.3 避免回表

在InnoDB的存储引擎中,使用辅助索引查询的时候,因为辅助索引叶子节点保存的数据不是当前记录的数据而是当前记录的主键索引,索引如果需要获取当前记录完整数据就必然需要根据主键值从主键索引继续查询。这个过程我们成位回表。想想回表必然是会消耗性能影响性能。那如何避免呢?

使用索引覆盖,举个例子:现有User表(id(PK),name(key),sex,address,hobby…)

如果在一个场景下,select id,name,sex from user where name ='zhangsan';这个语句在业务上频繁使用到,而user表的其他字段使用频率远低于它,在这种情况下,如果我们在建立 name 字段的索引的时候,不是使用单一索引,而是使用联合索引(name,sex)这样的话再执行这个查询语句是根据辅助索引查询到的结果就可以获取当前语句的完整数据。这样就可以有效地避免了回表再获取sex的数据。

3.4 覆盖索引

覆盖索引并不是说是索引结构,覆盖索引是一种很常用的优化手段。因为在使用辅助索引的时候,我们只可以拿到主键值,相当于获取数据还需要再根据主键查询主键索引再获取到数据。但是试想下这么一种情况,在上面abc_innodb表中的组合索引查询时,如果我只需要abc字段的,那是不是意味着我们查询到组合索引的叶子节点就可以直接返回了,而不需要回表。这种情况就是覆盖索引。

覆盖索引的情况:
mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构

未使用到覆盖索引:

mysql聚集索引和非聚集索引,mysql,mysql,数据库,b树,数据结构文章来源地址https://www.toymoban.com/news/detail-602057.html

到了这里,关于【mysql】聚簇索引和非聚簇索引(B树和B+树)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • MySQL 底层数据结构 聚簇索引以及二级索引 Explain的使用

    我们知道MySQL的存储引擎Innodb默认底层是使用B+树的变种来存储数据的 下面我们来复习一下B树存储 + B树存储  + 哈希存储的区别 哈希存储,只能使用等值查询 B树与B+树存储 我们知道B+树实际上就是B树的变种 那么为啥使用B+树而不是使用B树呢? 我们知道效率的高低主要取决于

    2024年04月28日
    浏览(34)
  • 重学MySQL之关系型数据库和非关系型数据库

    1.1 关系型数据库的特性 1.1.1 事务的特性 事务,是指一个操作序列,这些操作要么都执行,或者都不执行,而且这一序列是无法分隔的独立操作单位。也就是符合原子性(Atomicity)、 一致性(Consistency)、 隔离性(Isolation)和持久性(Durability)的一组操作。 原子性:指一个

    2024年02月02日
    浏览(62)
  • 【随手记】聚簇索引、二级索引和联合索引

    聚簇索引(Clustered Index) : 特点 :聚簇索引是表中数据行的物理排序方式,每张表只能有一个聚簇索引。通常,聚簇索引与主键相关联,但如果没有显式定义主键,则InnoDB存储引擎会选择一个唯一非空列作为聚簇索引。 联系 :聚簇索引实际上是表的主要排序顺序,因为它

    2024年02月06日
    浏览(27)
  • MySQL数据库:索引

            索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。         相当于是给数据库中的数据建立了一个目录,通过目录可以知道数据所在位置,然后到指定位置

    2023年04月17日
    浏览(56)
  • 【MySql】数据库索引

    可以简单理解为一本书的目录信息,是为了提升查找效率而建立的 1、在创建一个主键、唯一键、外键时候,数据库会自动地针对查找字段设置索引; 2、在创建表时侯,使用 index 进行普通索引的声明 3、修改表结构,给指定的字段添加索引 alter table 表名 add index 索引名

    2024年02月03日
    浏览(42)
  • MySQL数据库索引机制

    MySQL是一款有客户端和服务端的网络应用,mysql是它的客户端,mysqld是它的服务端。服务端本质就是一个进程,它存在于内存当中。而我们存储在MySQL中的数据是保存在磁盘上的,当我们对MySQL中数据进行增删查改操作时,不可能是直接在磁盘上进行操作,而是将对应的数据加

    2024年02月12日
    浏览(48)
  • MySQL数据库唯一索引

    创建索引是指在某个表的一列或多列上建立一个索引,以便提高对表的访问速度。创建索引有3种方式,分别是1.创建表的时候创建索引、2.在已经存在的表上创建索引和使用3.ALTER TABLE语句来创建索引。 本文福利, 莬 费领取Qt开发学习资料包、技术视频,内容包括(C++语言基

    2024年02月08日
    浏览(38)
  • MySQL数据库索引的数据结构

    数据库索引的功能就是让查找更加的高效,所以索引的数据结构应该是能够加速查找的数据结构。 MySQL的innoDB存储引擎的索引的数据结构就是多叉搜索树中的b+树,这可以说是为索引量身定做的一个数据结构。 首先,索引可以通过主键,unique修饰创建,也可以直接使用sql语句

    2024年02月10日
    浏览(41)
  • 【MySQL数据库 | 第十七篇】索引以及索引结构介绍

    目录 前言: 索引简介:  索引结构:           二叉树索引结构         Tree(普通二叉树)         B-Tree(多路平衡查找树)         B+Tree          哈希索引数据结构 总结: 在实际生活中,我们对SQL语句进行优化实际上有很大一部分都是对索引进行优化,因此对索引

    2024年02月09日
    浏览(55)
  • 简单认识MySQL数据库索引

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ●索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址(类似于C语言的链表通过指针指向数据记录的内存地址)。 ●使用索引后可以不用扫描全表来定位某行的

    2024年02月16日
    浏览(52)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包