【MySQL 进阶之路】索引概述

第06章_索引

1.什么是索引

索引是存储引擎用于快速找到数据记录的一种数据结构,就好比一本教科书的目录部分,通过目录中找到对应文章的页码,便可快速定位到需要的文章。MySQL中也是一样的道理,进行数据查找时,首先查看查询条件是否命中某条索引,符合则通过索引查找相关数据,如果不符合则需要全表扫描,即需要一条一条地查找记录,直到找到与条件符合的记录。
在这里插入图片描述
当数据库中没有索引时,数据会随机存储在硬盘的不同位置。具体来说,假设我们要查找 Col 2 = 89 的记录,如果没有索引,数据库引擎必须从第一行开始逐行读取并比较 Col 2 的值。例如,从 Col 2 = 34 开始,发现不匹配,继续读取下一行,直到找到 Col 2 = 89 的记录。对于一个包含上千万条记录的大表,这种线性扫描的方式意味着需要进行数百万次的磁盘I/O操作,在这个过程中,最耗时的部分是磁盘I/O操作,因此在没有索引的情况下,查询性能会受到严重影响。

假如给数据使用 二叉树 这样的数据结构进行存储,如下图所示

在这里插入图片描述

对字段 Col 2 添加了索引,就相当于在硬盘上为 Col 2 维护了一个索引的数据结构,即这个 二叉搜索树。二叉搜索树的每个结点存储的是 (K, V) 结构key 是 Col 2,value 是该 key 所在行的文件指针(地址)

比如:该二叉搜索树的根节点就是:(34, 0x07)。现在对 Col 2 添加了索引,这时再去查找 Col 2 = 89 这条记录的时候会先去查找该二叉搜索树(二叉树的遍历查找)。读 34 到内存,89 > 34; 继续右侧数据,读 89 到内存,89==89;找到数据返回。找到之后就根据当前结点的 value 快速定位到要查找的记录对应的地址。我们可以发现,只需要 查找两次 就可以定位到记录的地址,查询速度就提高了。

这就是我们为什么要建索引,目的就是为了 减少磁盘I/O的次数,加快查询速率。

2. 索引及其优缺点

2.1 索引概述

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

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

索引是在存储引擎中实现的,因此每种存储引擎的索引不一定完全相同,并且每种存储引擎不一定支持所有索引类型。同时,存储引擎可以定义每个表的 最大索引数最大索引长度。所有存储引擎支持每个表至少16个索引,总索引长度至少为256字节。有些存储引擎支持更多的索引数和更大的索引长度。

2.2 优点

(1)高数据检索的效率,降低 数据库的IO成本 。通过创建唯一索引,可以保证数据库表中每一行 数据的唯一性

(2)在实现数据的 参考完整性方面,可以 加速表和表之间的连接 。换句话说,对于有依赖关系的子表和父表联合查询时, 可以提高查询速度。

(3)在使用分组和排序子句进行数据查询时,可以显著 减少查询中分组和排序的时间 ,降低了CPU的消耗。

2.3 缺点

(1)创建索引和维护索引要 耗费时间 ,并 且随着数据量的增加,所耗费的时间也会增加。

(2)索引需要占 磁盘空间 ,除了数据表占数据空间之 外,每一个索引还要占一定的物理空间, 存储在磁盘上 ,如果有大量的索引,索引文件就可能比数据文 件更快达到最大文件尺寸。

(3)虽然索引大大提高了查询速度,同时却会 降低更新表的速度 。当对表 中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度。

3.B+Tree的理解(InnoDB)

在这里插入图片描述

B+Tree 概念图

在这里插入图片描述
一个B+树的节点其实可以分成好多层,规定最下边的那层,也就是存放我们用户记录的那层为第 0 层, 之后依次往上加。之前我们做了一个非常极端的假设:存放用户记录的页 最多存放3条记录 ,存放目录项 记录的页 最多存放4条记录 。

一般情况下,我们用到的 B+树都不会超过4层 ,那我们通过主键值去查找某条记录最多只需要做4个页面内的查找(查找3个目录项页和一个用户记录页),又因为在每个页面内有所谓的 Page Directory (页目录),所以在页面内也可以通过 二分法 实现快速 定位记录。

B+树的形成和运行:B+树的形成是自底向上的,即从叶子节点开始,随着数据的插入和分裂,逐渐向上形成内部节点和根节点。而在运行过程中,查找数据是自顶向下的,从根节点开始,根据键值范围逐层向下查找,直到找到目标数据所在的叶子节点。

3.1 索引图解

新建一个表:

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

在这里插入图片描述
这个新建的 index_demo 表中有2个INT类型的列,1个CHAR(1)类型的列,而且我们规定了c1列为主键, 这个表使用 Compact 行格式来实际存储记录的。这里我们简化了index_demo表的行格式示意图:

在这里插入图片描述record_type :记录头信息的一项属性,表示记录的类型, 0 表示普通记录、 2 表示最小记 录、 3 表示最大记录、。
各个列的值 :这里只记录在 index_demo 表中的三个列,分别是 c1 、 c2 和 c3 。

3.2 常见索引的概念

聚簇索引(Clustered Index)

  • 定义:聚簇索引决定了表中数据的物理存储顺序。也就是说,数据的实际存储顺序会按照索引的顺序进行组织。每个表只能有一个聚簇索引,因为数据只能有一个存储顺序。
  • 主键与聚簇索引:通常情况下,数据库会自动将表的主键PRIMARY KEY)作为聚簇索引。如果你没有显式地定义聚簇索引,那么数据库会选一个唯一且非空的列作为聚簇索引。注意,如果你指定了一个非主键的列作为聚簇索引,主键会变成一个二级索引。

InnoDB中,聚簇索引的每个叶子节点存储了完整的数据记录。目录项(非叶子节点)包含了指向叶子节点的指针最小主键值,用于引导查找过程。聚簇索引的叶子节点是双向链表,这使得在叶子节点内可以进行高效的数据遍历。
在这里插入图片描述

目录项记录 和普通的 用户记录 的不同点:

  • 目录项记录 的 record_type 值是1,而 普通用户记录 的 record_type 值是0。
  • 目录项记录只有 主键值和页的编号 两个列,而普通的用户记录的列是用户自己定义的,可能包含 很多列 ,另外还有InnoDB自己添加的隐藏列。

相同点:两者用的是一样的数据页,都会为主键值生成 Page Directory (页目录),从而在按照主键值进行查找时可以使用 二分法 来加快查询速度。

在这里插入图片描述
问题:如果我们表中的数据非常多则会产生很多存储目录项记录的页,那我们怎么根据主键值快速定位一个存储目录项记录的页呢?

回答

那就为这些存储目录项记录的页再生成一个更高级的目录,就像是一个多级目录一样,大目录里嵌套小目录,小目录里才是实际的数据,所以现在各个页的示意图就是这样子。

如图,我们生成了一个存储更高级目录项的 页33 ,这个页中的两条记录分别代表页30和页32,如果用 户记录的主键值在 [1, 320) 之间,则到页30中查找更详细的目录项记录,如果主键值 不小于320 的 话,就到页32中查找更详细的目录项记录。

二级索引(Secondary Index)

  • 定义:二级索引是指除了聚簇索引之外,基于表中的其他列(非主键列)建立的索引。 二级索引的目录项和聚簇索引类似,包含了指向叶子节点的指针和最小索引值。因此,二级索引实际上间接指向了表中的数据行。

在这里插入图片描述

分析一下!

  1. 叶子节点的内容
    • 在二级索引的B+树中,叶子节点存储的并不是完整的用户记录,而是C2列+主键这两个列的值。这意味着叶子节点不包含除索引列和主键之外的其他列值。
  2. 目录项记录的结构
    • 目录项记录中不再是主键+页号的搭配,而是C2列+页号的搭配。这意味着在非叶子节点中,每个目录项记录存储的是索引列的值和指向下一个目录项或叶子节点的页号。
  3. 记录的完整性
    • 在二级索引的B+树中,所有记录都不包括主键之外的其他列值。这意味着在叶子节点中,每个记录只包含索引列的值主键值,而不包含完整的用户记录。

二级索引的B+树结构与聚簇索引的B+树的区别,主要体现在叶子节点的内容、目录项记录的结构和记录的完整性上。 二级索引的叶子节点只包含索引列的值和指向主键的指针,而不包含完整的用户记录。

回表概念

我们根据这个以c2列大小排序的B+树只能确定我们要查找记录的主键值,如果我们想根 据c2列的值查找到完整的用户记录的话,仍然需要到 聚簇索引 中再查一遍,这个过程称为 回表 。也就是根据c2列的值查询一条完整的用户记录需要使用到 2 棵B+树!

问题为什么我们还需要一次 回表 操作呢?直接把完整的用户记录放到叶子节点不OK吗?

回答

如果把完整的用户记录放到叶子结点是可以不用回表。但是太占地方了,相当于每建立一课B+树都需要把所有的用户记录再都拷贝一遍,这就有点太浪费存储空间了。

因为这种按照非主键列建立的B+树需要一次回表操作才可以定位到完整的用户记录,所以这种B+树也被称为二级索引,或者辅助索引。由于使用的是c2列的大小作为B+树的排序规则,所以我们也称这个B+树为c2列简历的索引。

非聚簇索引的存在不影响数据在聚簇索引中的组织,所以一张表可以有多个非聚簇索引。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

小结:聚簇索引与非聚簇索引的原理不同,在使用上也有一些区别:

  1. 聚簇索引的叶子节点存储的就是我们的数据记录, 非聚簇索引的叶子节点存储的是数据位置。非聚簇索引不会影响数据表的物理存储顺序。
  2. 一个表只能有一个聚簇索引,因为只能有一种排序存储的方式,但可以有多个非聚簇索引,也就是多个索引目录提供数据检索。
  3. 使用聚簇索引的时候,数据的查询效率高,但如果对数据进行插入,删除,更新等操作,效率会比非聚簇索引低。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/928153.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微积分复习笔记 Calculus Volume 2 - 3.3 Trigonometric Substitution

3.3 Trigonometric Substitution - Calculus Volume 2 | OpenStax

业财一体化新篇章:外贸ERP软件重塑业务流程

业财一体化的定义(Definition) FMS,即财务管理软件(Financial Management Software),涵盖了用于管理公司财务的多种工具和系统,包括预算管理、账务处理、报表生成等功能。 ERP,即企…

Qt 信号与槽:UI设计的基础

Qt 的信号与槽机制是其最强大的功能之一,也是初学者理解 Qt 的第一步。它让对象之间的通信变得直观和高效。信号与槽类似于现实生活中的“呼叫和应答”模式:一个对象发出信号,另一个对象响应并执行动作。 什么是信号与槽? 信号与…

QT 左右 上下,拉伸 分配窗口大小

要的效果是以下: QT C 两个QWideget A B现在有放在一个窗口QWideget Test内,初始比例要2:8 ,现在我要 A B 两个窗口中间 当鼠标移到他中间时,有条线,可以左右移动来控件 A B 窗口所占的大小widgetB (有 wi…

Linux 各个目录作用

刚毕业的时候学习Linux基础知识,发现了一份特别好的文档快乐的 Linux 命令行,翻译者是happypeter,作者当年也在慕课录制了react等前端相关的视频,通俗易懂,十分推荐 关于Linux的目录,多数博客已有详细介绍…

基于PyTorch框架的线性回归实现指南

目录 ​编辑 1. 线性回归基础 2. PyTorch环境搭建 3. 数据准备 4. 定义线性回归模型 5. 损失函数和优化器 6. 训练模型 7. 评估模型 8. 结论 线性回归是统计学和机器学习中最基本的预测模型之一,它试图找到输入特征和输出结果之间的线性关系。在深度学习框…

HYSPLIT下载及使用

准备工作 官网基础教程:https://www.ready.noaa.gov/documents/Tutorial/html/index.html 使用 参考:https://blog.csdn.net/liaohaibing/article/details/112788701 下载之前还需要Graphical Utilities:https://www.ready.noaa.gov/HYSPLI…

基于Java Springboot环境保护生活App且微信小程序

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA/eclipse 微信…

骨架行为识别-论文复现

✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…

【PyTorch】torch.distributed.elastic.multiprocessing.errors.ChildFailedError:

报错说明 torch.distributed.elastic.multiprocessing.errors.ChildFailedError: 报错如图所示 报错分析 该报错是 torch 和 CUDA 版本不兼容导致。 (一般N卡自带的CUDA版本与最新的torch版本相差较大) 解决方案 1.查看自己的CUDA版本 # 查看自己的…

Kylin Server V10 下基于Kraft模式搭建Kafka集群

一、Kraft 模式与 ZooKeeper 模式简介 在Kafka 2.8 之前,Kafka 重度依赖 ZooKeeper 集群做元数据管理、Controller 的选举等(统称为共识服务);当ZooKeeper 集群性能发生抖动时,Kafka 的性能也会受到很大的影响。如下图所示: 在 Kafka 2.8 之后,引入了基于 Raft …

ceph手动部署

ceph手动部署 一、 节点规划 主机名IP地址角色ceph01.example.com172.18.0.10/24mon、mgr、osd、mds、rgwceph02.example.com172.18.0.20/24mon、mgr、osd、mds、rgwceph03.example.com172.18.0.30/24mon、mgr、osd、mds、rgw 操作系统版本: Rocky Linux release …

记录vite关于tailwindcss4.0-bate4出现margin[m-*]、padding[p-*]无法生效的问题。

环境如下: vite:5.4.10 tailwindcss: 4.0.0-beta.4 tailwindcss/vite: 4.0.0-beta.4 4.0默认的样式优先级比较低 如果使用了一些reset的css文件 那么很多样式会失效 例如:reset.css中 html, body, ul, li, h1, h2, h3, h4, h5, h6, dl, dt, dd, ol, i…

AcWing 841. 字符串哈希

字符串哈希 一种将任意长度的字符串转换为固定长度数值(通常是整数)的过程。全称字符串前缀哈希法,把字符串变成一个p进制数字(哈希值),实现不同的字符串映射到不同的数字。 对形如 X1X2X3⋯Xn−1Xn 的字…

物联网接入网关的数据安全和高效传输详解

物联网接入网关,作为连接物联网终端设备与云端或本地服务器的关键环节,不仅负责数据的汇聚与转发,更需确保数据在传输过程中的安全无虞与高效流畅。 一、数据安全:构筑坚实防线 1. 加密技术的应用 天拓四方物联网接入网关内置了…

遇到问题:hive中的数据库和sparksql 操作的数据库不是同一个。

遇到的问题: 1、hive中的数据库和sparksql 操作的数据库不同步。 观察上面的数据库看是否同步 !!! 2、查询服务器中MySQL中hive的数据库,发现创建的位置没有在hdfs上,而是在本地。 这个错误产生的原因是&…

电脑关机的趣味小游戏——system函数、strcmp函数、goto语句的使用

文章目录 前言一. system函数1.1 system函数清理屏幕1.2 system函数暂停运行1.3 system函数电脑关机、重启 二、strcmp函数三、goto语句四、电脑关机小游戏4.1. 程序要求4.2. 游戏代码 总结 前言 今天我们写一点稍微有趣的代码,比如写一个小程序使电脑关机&#xf…

【洛谷】P5738 【深基7.例4】歌唱比赛(详细注解)

#include <iostream> #include <iomanip> #include <algorithm> using namespace std;int main() {//定义两个整数变量n和m&#xff0c;用于接收用户输入的二维数组的行数和列数int n, m;cin >> n >> m;//定义二维整数数组A&#xff0c;用于存储…

SL6115替代MT7201C+MT7202内置60V场效应管降压恒流芯片

一、SL6115芯片特点 工作电压范围&#xff1a;SL6115的工作电压从5.5V到60V&#xff0c;提供了更宽的输入电压选择。 输出电流&#xff1a;SL6115提供可调的输出电流&#xff0c;最大输出电流可达到1.5A&#xff0c;相比MT7201C的1A输出电流&#xff0c;具有更高的驱动能力。…

利用Milvus向量数据库实现GraphRAG

大家好&#xff0c;GraphRAG技术借助知识图谱&#xff0c;给RAG应用注入了新的动力&#xff0c;使其能够在海量数据中精确检索所需信息。本文将介绍GraphRAG的实现方法&#xff0c;包括如何创建索引以及如何利用Milvus向量数据库进行查询&#xff0c;助力在信息检索的道路上事半…