当前位置: 首页 > news >正文

数据库之索引<保姆级文章>

目录:

一. 什么是索引

二. 索引应该选择哪种数据结构

三. MySQL中的页

四. 索引分类及使用


一. 什么是索引:

1. MySQL的索引是⼀种数据结构,它可以帮助数据库高效地查询、更新数据表中的数据
索引通过 ⼀定的规则排列数据表中的记录,使得对表的查询可以通过对索引的搜索来加快速度
2.MySQL 索引类似于书籍的目录,通过指向数据行的位置,可以快速定位和访问表中的数据,如汉语字典的目录(索引)页,我们可以按笔画、偏旁部首、拼音等排序的目录(索引)快速查找到需要的字。
 
3. 使⽤索引的⽬的只有⼀个,就是提升数据检索的效率,在应⽤程序的运⾏过程中,查 询操作的频率远远⾼于增删改的频率

二. 索引应该选择哪种数据结构:

 下面让我们来逐个分析:

1.哈希:

如果我们使用第一种:哈希,哈希确实是一种很优秀的数据结构时间复杂度是 O(1) 查询速度非常快,但是但是MySQL并没有选择哈希,主要原因是哈希不支持持范围查找,哈希是通过哈希函数构建的,由数组+链表或红黑树组成,是通过哈希函数来定位,因此哈希不支持持范围查找。 

 


2.叉搜索树:

如果我们使用二叉搜索树的中序遍历是⼀个有序数组

但有几个问题导致它不适合用作索引的数据结构:

2.1.最坏情况下时间复杂度为O(N)

2.2.相关搜索树AVL和红⿊树 节点个数过多无法保证树高:
包括AVL和红⿊树,虽然是平衡或者近似平衡,但是毕竟是⼆叉结构
在检索数据时,每次访问某个节点的⼦节点时都会发⽣⼀次磁盘IO,⽽在整个数据库系统中,IO是性能的瓶颈,减少IO次数可以有效的提升性能,所以树高导致磁盘IO次数多是个硬伤。所以MySQL并也没有选择搜索树
 

 
3.N叉树
通过观察,相同数据量的情况下,N叉树的树⾼可以得到有效的控制,也就意味着在相同数据量的情况下可以减少IO的次数,从而提升效率。但是MySQL认为N叉树做为索引的数据结构还不够好
  
 

 
4.B+树:
B+树是⼀种经常用于 数据库和文件系统 等场合的平衡查找树, MySQL索引采用的数据结构
该数据结构解决了树高 导致磁盘IO次数多问题 ,解决了范围查询问题,由于 叶子节点保存着所有数据,性能也比较均衡。
5. B+树 特点
5.1.能够保持数据稳定有序,插入与修改有较稳定的时间复杂度
5.2.非叶子节点仅具有索引作用,不存储数据,所有叶子节点保存着所有数据
5.3.所有叶子节点构成⼀个有序链表,可以按照主键值排序的次序依次遍历全部数据

6. B+树与B树的对比
6.1.叶子节点中的数据是连续的,且相互链接,便于区间查找和搜索。
6.2.⾮叶⼦节点的值都包含在叶⼦节点中
6.3.对于B+树⽽⾔,在相同树⾼的情况下,查找任⼀元素的时间复杂度都⼀样,性能均衡



三. MySQL中的页(每一个节点就是一页):

1.为什么要使用页:
.ibd ⽂件中最重要的结构体就是Page(页),页是内存与磁盘交互的最⼩单元,默认⼤⼩为
16KB每次内存与磁盘的交互⾄少读取一页,所以在磁盘中每个页内部的地址都是连续的,之所以这样做,是因为在使⽤数据的过程中,根据局部性原理将来要使用的数据大概率与当前访问的数据在空间上是临近的 ,所以⼀次从磁盘中读取一页的数据放⼊内存中,当下次查询的数据还在这个页中时就可以从内存中直接读取,从而减少磁盘I/O提高性能。
 (解释:上面的.ibd ⽂件,是innodb储存引擎,生成的文件。)
注意:每⼀个页中即使没有数据也会使用 16KB 的存储空间,同时与索引的B+树中的节点对应,这里可以查看页大小:使用命令: show variables like ' innodb_page_size ';

2. 局部性原理:
是指程序在执⾏时呈现出局部性规律,在⼀段时间内,整个程序的执⾏仅限于程序中的某⼀部分。相应地,执⾏所访问的存储空间也局限于某个内存区域,局部性通常有两种形式:时间局部性和空间局部性。
时间局部性 (Temporal Locality): 如果⼀个信息项正在被访问,那么在近期它很可能还会被再次访问。
空间局部性 (Spatial Locality): 将来要⽤到的信息⼤概率与正在使⽤的信息在空间地址上是临近的。 
 

 
 
 
3.页文件头和页文件尾:
在MySQL中有多种不同类型的页,最常⽤的就是⽤来存储数据和索引的"索引⻚",也叫做"数据⻚",但不论哪种类型的⻚都会包含⻚头,和⻚尾页的主体信息使用数 据"⾏"进⾏填充,数据⻚的基本结构如下:
页文件头和页文件尾如图所示:
  
这里上一页页号和下一页页号,通过这两个属性可以把页与页之间链接起来,形成⼀个
双向链表。 
 

 
 
 
4.页主体: 
页主体部分是保存真实数据的主要区域,每当创建⼀个新页,都会⾃动分配两个行⼀个是页内最⼩行Infimun ,另⼀个是页内最⼤⾏ Supremun 这两个行并不存储任何真实信息,⽽是做为数据⾏链表的头和尾,第⼀个数据⾏有⼀个记录下⼀⾏的地址偏移量的区域 next_record 将⻚内所有数据行组成了⼀个单向链表
当向一个新页插⼊数据时,将 Infimun 连接第⼀个数据行,最后⼀⾏真实数据行连接
Supremun ,这样数据行就构建成了⼀个单向链表,更多的行数据插⼊后,会按照主键从⼩到⼤的顺序进行链接
此时新 的结构如下所示
  
5.页目录 :
 
1.说明:⼀个⻚有16KB,通常会存在数百数据,每次都要遍历数百⾏,⽆法满⾜⾼效查
询,为了提⾼查询效率,InnoDB采⽤⼆分查找来解决查询效率问题  
 2. 因此加入 页目录 这个结构:
将页内包括头行、尾⾏在内的所有⾏进⾏分组,约定头行单独为⼀组,其他每个组最多8条数据,同时把每个组最后⼀行在页中的地址,按主键从⼩到⼤的顺序记录在页⽬录中在,页⽬录中的每⼀个位置称为⼀个槽,每个槽都对应了⼀个分组,⼀旦分组中的数据行超过分组的上限8个时,就会分裂出⼀个新的分组;后续在查询某⾏时,就可以通过⼆分查找,先找到对应的槽,然后在槽内最多8个数据行中进行遍历即可,从⽽⼤幅提高了查询效率,这时⼀个页的核⼼结构就完成了
总结:分组时会在页目录中创建一个个的槽,最小行单独为一组,⼀旦分组中的数据行超过分组的上限8个时,就会分裂出⼀个新的分组,槽指向对应分组的最后一条记录,并且储存该组的主键值,方便来 ⼆分查找。


6. B+在MySQL索引中的应用 :
注意:
(1).非叶子节点存的是索引页的信息
(2).索引页保存的是主键和子节点的引用信息。
(3).叶子节点保存的是真实数据的信息
(4).叶子节点形成一个双向链表
1.以查找id为5的记录,完整的检索过程如下:
步骤一:首先找到这条记录所对页
步骤二:再找到对应的槽
步骤三:根据槽的主键值,通过二分查找找到对应的记录。
具体如下:
首先判断B+树的根节点中的索引记录,此时 5 < 7 ,应访问左孩⼦节点,找到索引页2
然后在索引页2中判断主键id的大小,找到对应的槽的主键值与之不对
最后槽的主键值,通过二分查找找到对应的记录 找到与5相等的记录,命中,加载对应的数据页。
注意:这里每进行一次查找之前都要进行一次IO加载到内存,遍历几个节点IO几次。

2.三层B+树数据存放数(略)

索引⻚⼀条数据的⼤⼩为,主键⽤BIGINT类型占8Byte,下⼀⻚地址6Byte,⼀共14Byte,⼀个 索引页可以保存 16*1024/14 = 1170 条索引记录

综合只保存索引的根节点和⼆级节点的索引⻚以及保存真实数据的数据页,那么⼀共可以保存 1170*1170*16 = 21,902,400 条记录,也就是说在两千多万条数据的表中,可以通过三次IO就完成数据的检索



四. 索引分类及使用:

注意:创建多少索引就会生成多少索引树
1.主键索引:
当在⼀个表上定义⼀个主键 PRIMARY KEY 时,InnoDB使⽤它作为聚集索引 
代码:创建主键两种方式:
方式三:修改表中的列为主键索引:(修改表中的id列为主键索引)
语法:添加:ALTER TABLE + 表名 add PRIMARY KEY (...)
修改:ALTER TABLE + 表名 modify ...

 

2. 唯⼀索引:
当在⼀个表上定义⼀个唯⼀键 UNQUE 时,自动创建唯⼀索引
与普通索引类似,但区别在于唯⼀索引的列不允许有重复值
下图是创建索引的三种方式:
3.普通索引:
最基本的索引类型,没有唯⼀性的限制
可能为多列创建组合索引,称为复合索引或组和索引
 
方式一:创建表的时候创建普通索引
-- 创建表的时候创建普通索引
CREATE TABLE t_index1 (id bigint PRIMARY KEY auto_increment,name varchar(20) UNIQUE,sno varchar(20),index(sno)
)

方式二:修改表中的列为普通索引

修改表中的列为普通索引
CREATE TABLE t_index2 (id BIGINT PRIMARY KEY auto_increment,name VARCHAR(20),sno VARCHAR(20));ALTER TABLE t_index2 ADD INDEX (sno);

方式三:单独创建索引并指定索引名

 -- 单独创建索引并指定索引名 
CREATE TABLE t_index3 (id bigint PRIMARY KEY auto_increment,name varchar(20),sno varchar(20)
);-- 索引名推荐使用 idx_表名_列名[_列名]
CREATE INDEX idx_t_index3 on t_index3(sno);

 

创建普通索引三种方式:

-- 创建复合索引:-- 创建表时指定索引列
create table t_index_4 (id bigint PRIMARY key auto_increment,name varchar(20),sno varchar(20),class_id bigint,INDEX(sno,name)
)-- 单独创建复合索引并指定索引名
create table t_index_6 (id bigint PRIMARY key auto_increment,name varchar(20),sno varchar(20),class_id bigint
);CREATE INDEX idx__t_index_6_sno_name ON t_index_6 (sno,name);

 

4.全⽂索引:
4.1。基于⽂本列(CHAR、VARCHAR或TEXT列)上创建,以加快对这些列中包含的数据查询和4.2.DML操作
4.3.用于全文搜索,仅MyISAM和InnoDB引擎支持 
 
 
5.聚集索引:
与主键索引是同义词 如果没有为表定义 PRIMARY KEY, InnoDB使⽤第⼀个 UNIQUE 和 NOT NULL 的列作为聚集索引
注意:
如果表中没有 PRIMARY KEY 或合适的 UNIQUE 索引InnoDB会为新插⼊的行生成⼀个⾏号并用6字节的 ROW_ID 字段记录, ROW_ID 单调递增,并使⽤ ROW_ID 做为索引 
 
6 非聚集索引:
6.1.聚集索引以外的索引称为非聚集索引或⼆级索引
6.2.⼆级索引中的每条记录都包含该⾏的主键列,以及⼆级索引指定的列。
6.3.InnoDB使⽤这个主键值来搜索聚集索引中的⾏,这个过程称为回表查询 
 
7.非聚集索引的查询->回表查询解释 :
我们知道创建多少索引就会生成多少索引树.
我的理解是,通过索引查询到叶子节点的索引记录根据这个索引记录去整棵包含全部数据的索引树中查找数据的过程,因为总共查询了两张表索引叫回表查询。
例子:
-- 回表查询
select * from student where student_id = 1 and name = '韩立';

8.索引覆盖:
通过索引查询的列 不需要 根据索引记录 去整棵 包含全部数据的 索引树中查找 数据
例子:
select sn from student where name = '厉飞羽';

 

相关文章:

数据库之索引<保姆级文章>

目录&#xff1a; 一. 什么是索引 二. 索引应该选择哪种数据结构 三. MySQL中的页 四. 索引分类及使用 一. 什么是索引&#xff1a; 1. MySQL的索引是⼀种数据结构&#xff0c;它可以帮助数据库高效地查询、更新数据表中的数据。 索引通过 ⼀定的规则排列数据表中的记录&#x…...

多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测

多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测 目录 多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于BO-LSSVM贝叶斯优化最小二乘支…...

Netty笔记03-组件Channel

文章目录 Channel概述Channel 的概念Channel 的主要功能Channel 的生命周期Channel 的状态Channel 的类型channel 的主要方法 ChannelFutureCloseFuture&#x1f4a1; netty异步提升的是什么要点总结 Channel概述 Channel 的概念 在 Netty 中&#xff0c;Channel 是一个非常重…...

1----安卓机型修复串码 开启端口 檫除基带 支持高通与MTK机型工具预览与操作解析

在玩机过程中。很多玩家会碰到各种各样的故障 。其中最多的就在于基带 串码类。由于目前的安卓机型必须修改或者写入串码等参数必须开启端口。而一些初级玩友不太了解开启参数端口的步骤。这个工具很简单的为安卓机型开启端口。并且操作相对简单。 此工具基本功能 1-----可以…...

Docker容器技术1——docker基本操作

Docker容器技术 随着云计算和微服务架构的普及&#xff0c;容器技术成为了软件开发、测试和部署过程中的重要组成部分。其中&#xff0c;Docker作为容器技术的代表之一&#xff0c;以其简便易用的特点赢得了广大开发者的青睐。 Docker允许开发者在轻量级、可移植的容器中打包和…...

ElasticSearch介绍+使用

ElasticSearch 1.背景 ElasticSearch的最明显的优势在于其分布式特性&#xff0c;能够扩展到上百台服务器&#xff0c;极大地提高了服务器的容错率。在大数据时代背景下&#xff0c;ElasticSearch与传统的数据库相比较&#xff0c;能够应对大规模的并发搜索请求&#xff0c;同…...

Redis——常用数据类型List

目录 List列表常用命令lpushlpushxrpushrpushlrangelpoprpoplindexlinsertllenlremltrim key start stoplset 阻塞版本命令blpopbrpop list的编码方式list的应用 List列表 Redis中的list相当于数组&#xff0c;或者 顺序表&#xff0c;一些常用的操作可以通过下面这张图来理解…...

前端基础知识+算法(一)

文章目录 算法二分查找条件注意方式基本原理左闭右闭正向写法 左闭右开正向写法 前端基础知识定时器及清除盒子垂直水平居中的方式垂直水平1.flex布局2.grid布局3.定位对于块级元素 解决高度塌陷的方式1.给父元素一个固定的高度2.给父元素添加属性 overflow: hidden;3.在子元素…...

photozoom classic 9解锁码2024年最新25位解锁码

photozoom classic 9 破解版顾及比恐龙还要稀有&#xff0c;我曾经和你一样一直再找&#xff0c;找了好几个月&#xff0c;也没有找到真的破解版&#xff0c;下载很多次&#xff0c; 都是病毒插件之类的 我昨天下了几次&#xff0c;没有一个不附带插件病毒木马的.......&#x…...

Oracle发邮件功能:设置的步骤与注意事项?

Oracle发邮件配置教程&#xff1f;如何实现Oracle发邮件功能&#xff1f; Oracle数据库作为企业级应用的核心&#xff0c;提供了内置的发邮件功能&#xff0c;使得数据库管理员和开发人员能够通过数据库直接发送邮件。AokSend将详细介绍如何设置Oracle发邮件功能。 Oracle发邮…...

优化理论及应用精解【9】

文章目录 二次型函数二次型函数详细解释一、定义二、性质三、应用四、示例五、图表辅助说明&#xff08;由于文本限制&#xff0c;无法直接提供图表&#xff09; “西尔维斯特准则”一、定义二、来源三、应用场景 参考文献 二次型函数 二次型函数详细解释 一、定义 二次型函…...

nginx实现https安全访问的详细配置过程

文章目录 前言什么是 HTTP&#xff1f;什么是 HTTPS&#xff1f;HTTP 和 HTTPS 的区别为什么 HTTPS 被称为安全的&#xff1f;配置过程配置自签名证书 前言 首先我们来简单了解一下什么是http和https以及他们的区别所在. 什么是 HTTP&#xff1f; HTTP&#xff0c;全称为“超…...

1. TypeScript基本语法

TypeScript 学习总结 TypeScript 是一种 JavaScript 的超集&#xff0c;增加了静态类型检查和编译时错误检测&#xff0c;从而提高了代码的可维护性和可靠性。以下是 TypeScript 的基础知识总结&#xff0c;包括语法、运算符、数据类型、变量声明和作用域。 ## 基本语法TypeS…...

C# UDP与TCP点发【速发速断】模式

1、UDP 客户端 //由于收发都在本机&#xff0c;所以只用一个IP地址 IPAddress addr IPAddress.Parse("127.0.0.1"); var ptLocal new IPEndPoint(addr&#xff0c;9001);//本机节点&#xff0c;用于发送var ptDst new IPEndPoint(addr&#xff0c;9002);//目标节点…...

pikachu下

CSRF(跨站请求伪造) CSRF(get) url变成了这样了&#xff0c;我们就可以新开个页面直接拿url去修改密码 http://pikachu-master/vul/csrf/csrfget/csrf_get_login.php?username1&password2&submitLogin CSRF(post&#xff09; 这里只是请求的方式不同&#xff0c;…...

Go语言开发im-websocket服务和vue3+ts开发类似微信pc即时通讯

前言 IM即时通讯聊天, 为软件开发者打造&#xff0c;不依赖第三方sdk&#xff0c;完全用Go语言开发即时通讯服务&#xff0c;支持H5、Electron、Wails 、Uniapp和各种小程序的IM即时通讯, 快速实现私聊、群聊、在线客服&#xff01;让你快速搭建一个微信聊天系统&#xff0c;打…...

Redis如何实现分布式锁

目录 获取锁&#xff1a; 释放锁&#xff1a; Lua脚本&#xff1a; Redisson 分布式锁是&#xff0c;满足分布式系统或集群模式下多进程可见并且互斥的锁&#xff0c;因为我们熟知的java中的锁只是在单体架构下单个jvm中才会生效&#xff0c;如果部署了多个jvm则会导致新的…...

面向对象程序设计之继承(C++)

1.继承的定义 1.1继承的概念 继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段&#xff0c;它允许我们在保持原有类特性的基础上进⾏扩展&#xff0c;增加⽅法(成员函数)和属性(成员变量)&#xff0c;这样产⽣新的类&#xff0c;称派⽣类。继承 呈现了⾯向…...

IAPP发布《2024年人工智能治理实践报告》

文章目录 前言一、黑箱问题►透明度、可理解性与可解释性二、法律和政策中的注意事项►欧盟的《通用数据保护条例》►欧盟的AI法案►NIST的AI风险管理框架►美国的第14110号行政命令►《生成式人工智能服务管理暂行办法》►新加坡的AI验证三、实施人工智能治理►模型卡与系统卡…...

了解MySQL 高可用架构:主从备份

为了防止数据库的突然挂机&#xff0c;我们需要对数据库进行高可用架构。主从备份是常见的场景&#xff0c;通常情况下都是“一主一从/(多从)”。正常情况下&#xff0c;都是主机进行工作&#xff0c;从机进行备份主机数据&#xff0c;如果主机某天突然意外宕机&#xff0c;从机…...

图简记。。

模仿&#xff1a; algorithm-journey/src/class059/Code01_CreateGraph.java at main algorithmzuo/algorithm-journey Code01_CreateGraph C语言&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.h>#define MAXN 11 #define MAX…...

JVM 调优参数详解与实践

JVM 是 Java 程序性能的关键,合理的调优可以显著提升系统稳定性和吞吐量。本文将从基础参数出发,结合线上生产实践,对常用调优参数进行深入剖析与实战分享。 一、JVM内存结构概览 在进行JVM参数调优前,了解JVM内存结构非常关键 堆内存(Heap):用于存储对象,是GC主要处理…...

图像去雾数据集总汇

自然去雾数据集 部分的数据清洗可以看这里&#xff1a;图像去雾数据集的下载和预处理操作 RESIDE-IN 将ITS作为训练集&#xff0c;SOTSindoor作为测试集。训练集13990对&#xff0c;验证集500对。 目前室内sota常用&#xff0c;最高已经卷到PSNR-42.72 最初应该是dehazefo…...

Python数据可视化科技图表绘制系列教程(四)

目录 带基线的棒棒糖图1 带基线的棒棒糖图2 带标记的棒棒糖图 哑铃图1 哑铃图2 包点图1 包点图2 雷达图1 雷达图2 交互式雷达图 【声明】&#xff1a;未经版权人书面许可&#xff0c;任何单位或个人不得以任何形式复制、发行、出租、改编、汇编、传播、展示或利用本博…...

ES6 Promise 状态机

状态机&#xff1a;抽象的计算模型&#xff0c;根据特定的条件或者信号切换不同的状态 一、Promise 是什么&#xff1f; 简单来说&#xff0c;Promise 就是一个“承诺对象”。在ES6 里&#xff0c;有些代码执行起来需要点时间&#xff0c;比如加载文件、等待网络请求或者设置…...

[论文阅读] 人工智能 | 用大语言模型抓虫:如何让网络协议实现与RFC规范对齐

用大语言模型抓虫&#xff1a;如何让网络协议实现与RFC规范对齐&#xff1f; 论文信息 arXiv:2506.01249 SysLLMatic: Large Language Models are Software System Optimizers Huiyun Peng, Arjun Gupte, Ryan Hasler, Nicholas John Eliopoulos, Chien-Chou Ho, Rishi Mantr…...

STL 库基础概念与示例

一、STL 库基础概念与示例 1. 容器分类 顺序容器 核心特性&#xff1a;按元素插入顺序存储&#xff0c;支持下标访问&#xff08;类似数组&#xff09;&#xff0c;动态扩展内存。典型容器&#xff1a;vector&#xff08;动态数组&#xff09;。适用场景&#xff1a;需要频繁…...

你工作中涉及的安全方面的测试有哪些怎么回答

在面试或工作总结中&#xff0c;回答 **“工作中涉及的安全测试”** 时&#xff0c;可以结合具体场景、测试方法和工具&#xff0c;突出你的技术广度和深度。以下是结构化回答建议&#xff1a; --- ### **1. 分类说明安全测试范围** #### **(1) Web 应用安全测试** - **OWASP…...

BERT:让AI真正“读懂”语言的革命

BERT&#xff1a;让AI真正“读懂”语言的革命 ——图解谷歌神作《BERT: Pre-training of Deep Bidirectional Transformers》 2018年&#xff0c;谷歌AI团队扔出一篇核弹级论文&#xff0c;引爆了整个NLP领域。这个叫BERT的模型在11项任务中屠榜&#xff0c;甚至超越人类表现…...

ceph 对象存储用户限额满导致无法上传文件

查看日志 kl logs -f rook-ceph-rgw-my-store-a-5cc4c4d5b5-26n6j|grep -i error|head -1Defaulted container "rgw" out of: rgw, log-collector, chown-container-data-dir (init) debug 2025-05-30T19:44:11.573+0000 7fa7b7a6d700...