MySQL调优-深入理解MySQL索引底层数据结构与算法

news2024/11/15 17:31:25

目录

索引的定义

B-Tree

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

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

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

Hash

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

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

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

(4) hash冲突问题会发生

MyISAM存储引擎索引实现

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

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

InnoDB索引实现(聚集)

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

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

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

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

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

为什么使用联合索引?

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


索引的定义

索引是帮助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/134575.html

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

相关文章

基于pybind11的c++开发cuda算子用于python调用

一、环境 win10VS2022python39pybind11最新版git下载源码,后边会用:https://github.com/pybind/pybind11同时通过pip install pybind11,python环境下也要安装cuda环境配置参考:https://zhuanlan.zhihu.com/p/488518526二、cuda核函数动态库生成 步骤一:创建cuda项目 创…

VueElement

一、vue 1.1 概述 接下来我们学习一款前端的框架,就是VUE。 Vue 是一套前端框架,免除原生JavaScript中的DOM操作,简化书写。 我们之前也学习过后端的框架 Mybatis , Mybatis 是用来简化 jdbc 代码编写的;而 VUE 是前…

绝对路径和相对路径

目录 1说明 2.相对路径的优势 3.注意 4./说明 1说明 绝对路径:文件真实的存放位置 例:D:\data\applogs\xxl-job\xxl-job-admin.log 不需要知道其他任何信息就可以根据绝对路径判断出文件的位置 相对路径:相对于当前位置的路径 前端开…

QT学 控件(四)步长调节框(QSpinBox + QDateTimeEdit)

文章目录QSpinBoxQDateTimeEditQSpinBox 允许用户通过单击向上/向下按钮或按键盘上的上/下来选择一个值来增加/减少当前显示的值。用户还可以手动键入值 常用于处理 选择 : 【1-99】 【星期1一 - 星期天】【1月-12月】 样式: 继承自: QAb…

网络协议(二):MAC地址、IP地址、子网掩码、子网和超网

网络协议系列文章 网络协议(一):基本概念、计算机之间的连接方式 网络协议(二):MAC地址、IP地址、子网掩码、子网和超网 目录一、MAC地址二、IP地址1、IP地址的组成2、IP地址的分类三、子网划分1、等长子网划分2、变长子网划分四、超网五、判断一个网段…

DIY NAS服务器之OMV 5.6入坑指南(四) -安装docker和Portainer

系列文章目录 DIY NAS服务器之OMV 5.6入坑指南(一)-openmediavalut 5.6安装DIY NAS服务器之OMV 5.6入坑指南(二)- 安装omv-extras插件DIY NAS服务器之OMV 5.6入坑指南(三)- 切换系统源​​​​​​​ ​​…

CentOS安装Vscode-yum+Vscode前端开发必安装的插件

CentOS安装Vscode-yum Visual Studio Code 是 Microsoft 产品和开源跨平台代码编辑器。 它提供内置调试支持、代码完成、集成终端语法高亮、嵌入式 Git 控制、代码重构和代码片段。 在本教程中,我们将介绍如何使用 CentOS 7 机器上的官方代码存储库安装最新版本的…

Python--你见过雪飘人间吗?

happy new year 突然想来一点雪花特效。 其实Python做前端效果还是很少的,也就大概记录一下画法啦 对了祝大家新的一年快乐,早点脱单吧!!! 附上一张女神的照片 Python-turtle 科赫曲线是一种分形。其形态似雪花&am…

地宫夺宝(三种方法)(第五届蓝桥杯省赛C++A/B/C组,第五届蓝桥杯省赛JAVAB/C组)

PS:方法一和方法看起来复杂,但其实较容易理解,大家不要跳过哦。至于方法三的动态规划则可能有点抽象,理解起来有点难度。 目录 题目描述: 三种方法: 方法一:暴力枚举(该方法只能获得30分&…

函数传参问题,桶排序去重,分治递归,摩尔投票求数组众数,数组中心下标求法

TIPS 1. 我们都知道,地址,指针这两者是完全等价的概念,但是有微小的差别。地址的话是不能够修改的(比如说数组名就是违法的),而指针的话可以与--。 2. 以后一旦在代码里面看到字符char类型的,…

安全回顾总结

xss反射型漏洞复现 观察源码&#xff0c;可以看出源码中通过get传参到变量xss&#xff0c;并将一些特殊符号过滤了&#xff0c;则后续需要考虑该规则的绕过 echo “<img src”{$xss}">"; img标签 <img src“aaa” οnerrοr“alert(1)” 如果img图片不存在…

自然语言处理-01神经网络

数学和PY 向量是同时拥有大小和方向的量。向量可以表示为排成一排的数字集合&#xff0c;在 Python 实现中可以处理为一维数组。 向量和矩阵可以分别用一维数组和二维数组表示。另外&#xff0c;在矩阵中&#xff0c;将水平方向上的排列称为行&#xff08;row&#xff09;&…

2.SpringBoot-Condition

一、 参考 04-SpringBoot自动配置-切换内置web服务器_哔哩哔哩_bilibili 二、 Condition 顾名思义&#xff1a;条件。有点类似于if语句&#xff0c;只不过是通过注解的形式来实现。 以一个实际需求来学习该原理&#xff1a;有一个实体类User&#xff0c;想要创建该实例化对象…

Retrift

文章目录一、Retrift简介二、Retrift使用介绍三、注解1、GET2、POST3、PUT4、DELETE一、Retrift简介 retrift官网 1、是一个基于okhttp的网络请求框架 2、通过注解配置网络请求参数 3、图片链接和图片上传 4、支持同步和异步网络请求 5、支持多种数据的解析,提供对Rxjava的支…

光环:软件工程环境堆栈建设思路——徐磊

摘要&#xff1a;文章内容主要来源于光环国际2022年第三届中国科创者大会徐磊老师的分享&#xff0c;原分享名称为"企业开发者平台建设思路&#xff0c;云原生技术如何赋能开发者"。简述当前软件工程中Devops平台还缺少一个软件调试环境环节&#xff0c;这个环境其实…

stacking方法,boosting算法,与bagging的区别,adboost算法权重固定,regionboost权重动态学习

stacking方法&#xff0c;boosting算法&#xff0c;与bagging的区别&#xff0c;adboost算法权重固定&#xff0c;regionboost权重动态学习 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#…

VBA之正则表达式(38)-- 提取规格数据(1/2)

实例需求&#xff1a;A列为某产品名称&#xff0c;现需要提取其中的规格数据&#xff0c;具体规则如下&#xff1a; 规格数据以如下关键字开头&#xff1a;RO、RE、SQ、SD、QD、OB、HX、ET、QR、D2规则数据可能有多段&#xff08;截图中红色部分&#xff09;提取规格数据之后&…

数据模拟:利用Java模拟数据(姓名,邮箱,地址,电话等信息,时间,工资,1-10随机数)并存入mysql

学大数据分析的同学们在做数据分析时一般很难找到适合数据集&#xff0c;本文就来分享一下如何利用Java模拟数据&#xff0c;并将产生数据保存至mysql数据库中。 主要技术就是Java产生数据&#xff0c;利用mybatis存入mysql数据库 数据模拟项目1.数据库建表2.构建maven项目3.项…

初级指针【一】

指针是什么&#xff1f;2个要点&#xff1a;指针是内存中一个最小单元编号&#xff0c;也就是地址。平时口语中说的指针&#xff0c;通常指的是指针变量&#xff0c;是用来存放地址的变量。总结&#xff1a;指针就是地址&#xff0c;我们口语中说的指针指的是指针变量。指针的大…

ZooKeeper分布式协调服务(节点分类、事件监听、java集成)

文章目录前言安装启动相关概念操作节点事件监听java客户端前言 ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xf…