一篇深入理解MySQL索引底层数据结构与算法

news2024/9/23 5:25:53

索引的定义

索引是帮助MySQL高效获取数据的排好序数据结构

 

索引数据结构有:二叉树,红黑树,Hash表,B-Tree,B+Tree

对于数据库表的InndB索引来说,底层即是B+Tree数据结构

B-Tree

(1) 叶子节点具有相同的深度,叶子节点的指针为空

(2) 所有的索引元素不重复

(3) 节点中的数据索引从左到右递增排列

 B+Tree(B-Tree变种)

(1) 非叶子节点不存储data数据,只进行存储索引(这个索引是冗余的索引,多余的),可以放更多的索引

分析:

首先我们需要知道:一个数据页的大小MySQL原则规定为16KB(16384字节)。

1.如果以现在的B+树为例,非叶子节点只进行存储索引,一个索引大小为(8+6)个字节大小,一个索引包含指向下一个数据页的地址值和整形主键值。

那么非叶子节点的一个数据页可以存储(16384除以14==1170)1170条记录的索引。

假如说B+树为三层,那么第一层只有一个数据页,这一个数据页可以存储1170条记录的索引。

第一层这一个数据页中的每一条索引对应第二层一个数据页,所以第二层又对应有1170条数据页,一个数据页存储1170个索引,所以第二层可以存储1170X1170条索引。

第三层存储真实的data数据,一条数据记录假设为1KB,那么一个数据页可以存储16条data数据记录。第二层有1170X1170条索引,对应第三层可以存储1170X1170X16=千万级别data真实数据量。

 2.如果以之前的B树数据结构为例,非叶子节点的数据页中也进行存储的是data数据,一条数据记录大概为1KB,那么一条数据页仅仅存储16条记录。那么要达到千万级别的数据量存储需要16的n次方,这个层数将会远远大于3。

 

(2) 叶子节点包含所有的索引字段

分析:

对于B+树结构而言,非叶子节点存储的是冗余索引,这个冗余索引的作用就是确定真正的data数据是位于叶子节点中的哪一个位置的,通过的是二分法查找。所有真实的data数据是存储在叶子节点中的。

(3) 叶子节点用指针相互连接,提高区间访问的性能

分析:

相邻的叶子节点之间是用指针相互连接的,指针的具体实现是通过让相邻的节点划分一块内存空间用来互相存储对方节点的地址。

为什么要搞一个指针相互连接?

提高区间访问的性能。

举一个例子,假设说我们要查询一个区间范围的数据量(20~1000)。

1.如果是之前的B树结构,虽然叶子节点的数据也是从小到大进行排序的,但是相邻节点之间没有指针指向,当我们锁定了20后也无法直接一路向右锁定大于20的数据,我们还是要重新进行查询。

2.但如果是现在的B+树结构,当我们通过冗余索引锁定了叶子节点的元素20,那么通过这个相邻指针,我们可以一路向右查找,一直锁定到1000为止。因为叶子节点的元素是按照大小顺序从左往右排布的。

Hash

 

(1) 对索引的key进行一次hash计算就可以定位出数据存储的位置

分析:十分快速方便,但是MySQL底层使用的是B+树作为存储数据的存储结构

(2) 很多时候Hash索引要比B+树索引更加高效

分析:同(1)分析即可

(3) 仅能满足"=","IN",不支持范围查询

分析:相比B+树,该Hash结构不支持范围查询,因为Hash表是根据key键值生成哈希值,根据哈希值确定在哈希表哪一个索引,是随机的。

可能说一个key键值为"李四1",一个key键值为"李四2",这两个key键值生成的哈希值相差甚大,最终索引位置相差甚远!

所以不支持范围查询。

但是B+树的叶子节点中是把所有的数据记录从小到大依次存储的,并且相邻的叶子节点之间使用指针指向,适合范围查询。

(4) hash冲突问题会发生

分析:不同的key键值生成的哈希值相同,最终生成的索引值相同,不同的对象竞争想要存储到同一个索引位置,发生Hash冲突!

MyISAM存储引擎索引实现

MyISAM索引文件和数据文件是分离的(非聚集)

 

为什么Myisam引擎对应索引及数据为非聚集?InnoDB是聚集?

一张图告诉你结果:

 

InnoDB索引实现(聚集)

(1) 表数据文件本身就是按B+Tree组织的一个索引结构文件

(2) 聚集索引-叶子节点包含了完整的数据记录

(3) 为什么建议InnoDB表必须建主键,并且推荐使用整型的自增主键?

分析:

为什么建议InnoDB表必须建主键?

主键查询是极其高效的。

如果我们不主动建主键,InnoDB底层也会默认帮您在众多字段中,去选择一个字段作为主键(该字段必须满足字段对应的所有记录值都是不相同的,保证主键字段值的唯一性)。若没有满足该条件的字段作为主键的话,InnoDB底层会模拟一个rowid字段作为主键。但是InnoDB帮我们建主键所消耗的性能远超过自主建索引所消耗的性能,所以最好主动创建一个主键,一般选择的就是一个自增的id字段作为主键。

为什么推荐使用整型的自增主键?

使用整形:

是因为数据类型为整形的主键字段在我们使用主键查询操作的时候更加便于进行比对操作,如果使用数据类型为字符串的字段作为主键的话,我们根据主键索引进行查询操作时,比对是根据ASCII码表进行的,效率远不及整形直接比对!

使用自增:

数据底层存储使用的数据结构为B+树,B+树存储数据记录是在叶子节点中的。但是数据记录存储是从小到大依次进行排列存储的。

如果不使用自增字段插入,随意进行插入一个大小的字段,这个随意的大小字段会插入到任意的数据页中,那么很可能会造成页分裂等大消耗性能的情景。

如果使用自增字段插入,根据叶子节点中所有存储的记录是从小到大排列存储的原则:每一次新插入一个自增的记录是插入到最后面的叶子节点,当发现该叶子节点存储的数据达到一定时,下一个数据就不会再存储到这个叶子节点了,会新开辟一个叶子节点。因此页分裂的情况就不会再出现了,这样极大的节省性能消耗。

 

(4) 为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)

分析:

一个数据库表可能会有十几个,甚至二十几个字段,除了主键字段设置为主键索引外。其余的字段也可以进行设置索引,即是非主键索引,也称为二级索引。

为什么非主键索引结构叶子节点存储的是主键值?

(1)保证一致性

当通过非主键索引(二级索引)进行查询一条记录,我们需要先根据非主键索引结构叶子节点中存储的主键值进行一次回表操作,回表操作即是找到主键索引对应的B+树存储结构表,找到回表到的B+树存储结构的叶子节点,找到对应的数据记录。这样进行查询,即使数据库表记录更改,也可以保持数据一致性。

(2)节省存储空间

如果一新建一个非主键索引,叶子节点就进行存储所有的记录数据,这是十分浪费磁盘空间的。

 

联合索引的底层存储结构长什么样?

 

为什么使用联合索引?

  • "一个顶三个"。建了一个(a,b,c)的复合索引,那么实际等于建了(a),(a,b),(a,b,c)三个索引,因为每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,这可是不小的开销!

  • 覆盖索引。同样的有复合索引(a,b,c),如果有如下的sql: select a,b,c from table where a=1 and b = 1。那么MySQL可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机io操作。减少io操作,特别的随机io其实是dba主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一

  • 索引列越多,通过索引筛选出的数据越少。有1000W条数据的表,有如下sql:select from table where a = 1 and b =2 and c = 3,假设假设每个条件可以筛选出10%的数据,如果只有单值索引,那么通过该索引能筛选出1000W10%=100w 条数据,然后再回表从100w条数据中找到符合b=2 and c= 3的数据,然后再排序,再分页;如果是复合索引,通过索引筛选出1000w 10% 10% *10%=1w,然后再排序、分页,哪个更高效,一眼便知

通过分析下图这个案例说明索引最左前缀原理:

 分析:首先要明白索引的定义:索引是帮助MySQL高效获取数据的排好序数据结构

对于联合索引而言:只有当name字段的值大小一致相同时的那些记录,那些记录对应的age字段大小才是从小到大依次排好序的。(如图:name都是Bill的数据记录,对应的age才是从小到大依次排序的。对于HanMeiMei,Jeff这些不同name对应的age压根不是依次排序的)

 所以对于最左前缀原理的作用就在于此,因此对于联合索引而言:如果相对最左的字段不走索引,那么相对较右边的字段走索引也走不成。

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

生物化学 实验记录或传闻 简述(暂记)

今天是2023年的1月1日,2022年是疫情肆虐的一年,由于疫情的叨扰,我在22年的最后一个月博客更新停滞了许久,这同时引发了我对一些医学方面的问题的观察,所以我准备在“力学地球物理科学化学”专栏的生物化学部分新增一个…

opencv--颜色识别

目录 一、主要函数介绍 二、颜色识别 三、其他相关函数介绍 1. cv2.resize 2. np.array(x,dtype) 3. cv2.inRange() 4. cv2.imshow() 5.cv2. waitKey() 四、掩膜 一、主要函数介绍 通常,相机在RGB颜色模式下工作,但这种模式受到光线的影响较大&am…

2022年终总结-知识沉淀、疫情、展望未来

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA工作经验 一位上进心十足的【大数据领域博主】!😜&#x1f61…

GIS算法

目录 简介 GIS标准简介 空间数据模型 3.1 WKT与GeoJSON 3.2 WKB格式 GIS算法三方包 简介 地理信息系统(简称GIS),以数字化的形式反映人类社会赖以生存的地球空间的现势和变迁的各种空间数据以及描述这些空间数据特征的属性,支持空间数据及其属性数据的输入/输出,存储,显…

postgresql数据库主备安装,备份还原

一.postgresql数据库安装 1.下载软件包 地址:PostgreSQL: File Browser 2.解压安装 [rootpostgresql u01]# tar -zxf postgresql-14.2.tar.gz安装环境 yum install -y perl-ExtUtils-Embed readline-devel zlib-devel pam-devel libxml2-devel libxslt-devel op…

小说阅读 (支持txt文本文件浏览)

小说阅读2022 - 界面 2023年1月2日 更新 1、修复BUG。。。 2、优化运行。。。 3、添加了 【[阅读笔记] - 可以在章节处填写阅读笔记保存,程序会自动记录位置坐标,每次在读到本章节保存位置坐标时右上角会自动跳出提示图标,点击提示图标即可…

SAP FICO付款及清账

付款及清账 在SAP中,处理付款要达到两个效果: 实现会计凭证的处理; 实现清账(将付款与应付账款对应核销); 可以边付边清,也可以先付后清。 一、付款并清账 企业的付款一般有现金付款、银行存款…

Gem5模拟器,全流程运行Chiplet-Gem5-SharedMemory-main(十)

小白入门,跑着个代码头都给我跑秃了,文档说不详细吧似乎啥都和你说了,说它详细吧,看了几遍也跑不出来。记录一下我遇到的问题: 目录 一、确定待执行的程序 (1)那些年的undefined reference &…

(3分钟速通)Visual Odometry的特征点法和直接法

光流法:(https://zhuanlan.zhihu.com/p/537113460) ​ 编辑切换为居中 添加图片注释,不超过 140 字(可选) ​ 编辑切换为居中 添加图片注释,不超过 140 字(可选) ​ 编辑切换为居中 添加图…

【免费开放源码】审批类小程序项目实战(预约历史页面)

第一节:什么构成了微信小程序、创建一个自己的小程序 第二节:微信开发者工具使用教程 第三节:深入了解并掌握小程序核心组件 第四节:初始化云函数和数据库 第五节:云数据库的增删改查 第六节:项目大纲以及制…

Vue与React分别实现登录拦截【详细例子+讲解】

文章标题一、Vue实现登录拦截1-1、 效果展示1-2 代码展示1-2-1 router.js1-2-2 store文件夹下1-2-2-1 state.js1-2-2-2 index.js1-2-2-3 mutation.js1-2-3 main.js【实现登录拦截的关键---全局路由守卫】1-2-4 pages下的login.vue1-3 总结二、 Vue项目功能简介2-1 功能2-2 查看…

基于RBAC模型的权限控制的一整套基础开发平台,前后端分离,后端django,前端 vue+ElementUI

Django-Vue-Admin 完整代码下载地址:基于RBAC模型的权限控制的一整套基础开发平台 💡 「关于」 我们是一群热爱代码的青年,在这个炙热的时代下,我们希望静下心来通过Code带来一点我们的色彩和颜色。 因为热爱,所以…

TensorFlow之过拟合与欠拟合-1

1 基本概念 过度拟合(overfit) 创建的模型与用于该模型的训练数据之间发生过于密切的关系,从而引起该模型无法对新数据进行准确的预测。正则化(Regularization)策略可以减少过度拟合,或者使用大数据量、多…

考研数学660刷题记录

🐢🐢 基本概念-基本理论-基本方法 🐢🐢 660刷题记录 二轮复刷标志 ⭐:掌握不熟练 ⭐⭐:是基本方法的组合,但没解出来 ⭐⭐⭐:很难想到这种破局的手段 序号①、②:表示多…

【阶段一】Python快速入门02篇:数据结构-列表

本篇的思维导图: 数据结构-列表 列表的概念 列表(list)是用来存储一组有序数据元素的数据结构,元素之间用逗号分隔。列表中的数据元素应该包括在方括号中,而且列表是可变的数据类型,一旦创建了一个列表,你可以添加、删除或者搜索列表中的元素。在方括号中的数据可以是 i…

小程序:会议OA其他页面

目录 会议管理 一,自定义tabs组件 二,会议管理 父子组件传参演示 个人中心 会议管理 一,自定义tabs组件 文档参考:自定义组件 | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/miniprogram/dev/framework/custom-co…

MacBook 与其他设备的低成本高性能数据传输方案

本篇文章分享在不使用路由器的情况下,使用“数据线或网线”将 MacBook 与其他设备连接在一起,获得更高效率的数据交换性能。 写在前面 最近考虑将 Mac 设备和其他的设备连在一起使用,比如之前在“廉价的家用工作站方案:前篇”或…

利用Python实现酒店评论的中文情感分析,含数据集

利用Python实现酒店评论的情感分析 完整代码下载地址:利用Python实现酒店评论的中文情感分析 情感极性分析,即情感分类,对带有主观情感色彩的文本进行分析、归纳。情感极性分析主要有两种分类方法:基于情感知识的方法和基于机器学…

抽象类和接口1

目录 🌤️抽象类概念 🌤️抽象类语法 🌤️抽象类的作用 ⛅接口的概念 ⛅接口的语法 ⛅接口的使用 ⛅接口的特性 ....... 🌤️抽象类概念 在面向对象的概念中,所有对象都是通过类来描述的,但并不是所有的…

上手华为鸿蒙手表gt系列从准备到发布

文章目录1、前期准备2、证书&签名3、编码&发布FQA:问题1:The graphic card OpenGL version is too old for Previewer to work. It must be 3.2 or later. Update the OpenGL driver based on the graphics card model.问题2:编译成HAp,报错 ent…