当前位置: 首页 > 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;从机…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...

加密通信 + 行为分析:运营商行业安全防御体系重构

在数字经济蓬勃发展的时代&#xff0c;运营商作为信息通信网络的核心枢纽&#xff0c;承载着海量用户数据与关键业务传输&#xff0c;其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级&#xff0c;传统安全防护体系逐渐暴露出局限性&a…...