【MySQL】B+ 树索引
一、索引是什么 ? 为什么需要索引 ?
索引就是目录,目录就是索引。
索引从 InnoDB 存储引擎数据存储结构上来看,就是为各个页建立的目录。保证我们在查询时,可以通过二分法快速定位到页,再在页内通过二分法快速定位到组,再在组内进行查询。
背景知识:页分裂表示进行创建新页存放我们插入的数据的过程要求创建完的这些页中的记录具有主键值的递增关系。
二、为页建立的目录应该什么样子 —— 如何设计
为页建立目录,目录的目录项为 :
- 用户记录中最小的主键值
- 页号
1. 为页建立的目录也被封装成页了 —— 成了索引
因为 InnoDB 以页为单位,所以我们上面说的为页建立的目录也需要被放在一个页里。这个页就是目录项页,目录项页中的记录就是把目录项封装为记录,即目录页中的记录为 (页号, 用户记录中最小的主键值)
目录项记录和我们的数据页中的记录具有如下区别:
- 标志记录类型的值不同 —— 目录项记录的 record_type = 1, 普通用户记录为 0
- 记录的内容不同
2. 有了目录项页后的查找过程
- 在目录页中通过二分查找定位到所在的页
- 在所在页的页目录中通过二分查找进行查找
3. 目录项页也是个页,其存不下那么多目录项了咋办
新增新的目录项页就行了,然后再为这些目录项页抽象出一个目录项页的目录页 。 —— … 太厉害了 ~
然后我们就可以发现这个结构变成树了 —— 这个树就是 B+ 树, 就是我们 InnoDB 中的索引实现方式
然后我们再去想,我们的用户数据记录都在树的叶子节点(就是最下层),其他的目录的内容都在非叶子节点上 —— 这就是 B+ 树的特点
三、索引类型
1. 聚簇索引
我们上文说的 B+ 树就是个聚簇索引,它具有两个特点:
- 使用记录主键值进行排序
- B+ 树的叶子节点就是用户记录
InnoDB 会自动为我们创建聚簇索引,而且这个聚簇索引就是 InnoDB 的数据存储结构,嘿嘿嘿,一句非常好的话 —— 索引即数据,数据即索引
2. 二级索引
我们不可能一直通过主键进行查询,有时候也需要通过一些非主键的列进行查找。这时的索引的策略是对这个非主键列建立一颗 B+ 树(就是按照这个列进行排序建立二叉树),但是其 叶子节点 存放的值只有 : 索引列的值 + 主键值 + 页号 。 我们通过这个列得到要查找的记录的主键值,然后再拿着主键值进行回表 (就是再去聚簇索引那里查一遍),所以其需要遍历两棵 B+ 树,所以才叫 “二” 级索引鸭 ~~
注:为啥不全存上,为啥只存主键 id ,要是全存上不久不用回表了嘛 ? —— 空间 !! 空间 !!!
3. 联合索引
以多个列作为排序规则建立索引,本质上也是个二级索引
注: 排序方式为先按照第一个列,再按第二个列 …
四、用索引
1. 索引的缺点
占用空间 + 索引维护浪费时间
2. 什么情况下才使用到索引
背景: 创建索引 ——
- 在 创建表 时创建
key idx_rowname1_rowname2....(rowname1, rowname2, ....)
- 创建表之后,选择表创建
alter table table_name add key/index row_name
(1)情况一: 全值匹配
搜索条件的列和索引列一致,即我们建立了联合索引,然后我们的搜索条件刚刚好就是这个联合索引建立的列
注: 顺序没有影响, MySQL 的查询优化器会帮我们调整到最优顺序
(2)情况二: 匹配左面的列
联合索引中的列可以不全用到,只包含左面(一个或者多个列)就行 (理解联合索引的排序方式很重要 !!!)
联合索引的后面的列可以没有,可以不用,下面举个例子
用户记录为 :(row1, row2, row3, row4),假如一个联合索引是这样的 row2_row3_row4
这种情况都可以用到索引 : .... where row2 = value1 and row3=value2 and row1=value3
这种情况下我们可以用到 row2_row3 的索引,然后再筛选出 row1
这种情况就用不到索引了 : .... where row3 = value 或者 ... where row4 = value 等等
(3)匹配列前缀原则
根据字符集的比较规则,对于字符串类型的索引,可以只匹配前缀
where row like 'Prefix%'
但是注意: 不可以匹配中缀,或者后缀,只能是前缀,这是由字符集的排序规则决定的
如果需要比较后缀,可以把字符串逆序存储 …
(4)情况四:匹配范围
因为我们的记录是按照索引的大小用链表连着的,所以可以取出范围,但是对多个索引列同时进行范围查找的话,只能用到最左面的那个索引列。理由很清晰:
只有当前索引值相同,才按下一个索引排序,而这个是个范围,对这个范围内的第一个索引下面的查找的那个索引列的值不一定啥样子,所以只能用到最左面的第一个索引列
(5)其他情况
这都是根据索引构造的原理决定的,还有如下情况也能用到索引:
- 精确匹配 + 范围匹配
- 排序情况
- 分组
补充: 什么情况下排序不能用到索引
排序列不在索引里、按多个列进行排序的列不包含在一个联合索引里、排序列包含了复杂的表达式
3. 到底要不要回表
我们平时进行非范围查询, 这时候我们只需要拿着在 二级索引 中找到的 id,回表一次 聚簇索引就 ok 了
但是但我们进行范围查询时,我们是拿着一堆 id , 等着要去回表, 这些 id 不挨着,做的是 随机 io ,非常损耗性能。 —— 这种情况宁可全表扫描,也不要回表一堆次聚簇索引。
当然是否回表是 MySQL 优化器决定的,其会根据回表次数自己判断是要回表还是全表扫描。
但是我们可以通过 覆盖索引 的方式彻底摆脱回表。所以我们尽量不要 select *
五、什么样子的列适合建立索引
- 搜索、排序、分组的列
- 不咋重复的列 —— 比如具有唯一值的列
- 数据类型占用空间小的列 —— 比如数字类型
- 对字符串值的前缀建立索引
六、注意事项
- 不要在查询中对索引列瞎做运算,让索引列单独存在,不然不要索引列,而是挨个运算
- 使用自增主键,降低维护聚簇索引的成本
- 不要瞎建立一堆冗余索引,用一个联合索引就能解决
相关文章:
【MySQL】B+ 树索引
一、索引是什么 ? 为什么需要索引 ? 索引就是目录,目录就是索引。 索引从 InnoDB 存储引擎数据存储结构上来看,就是为各个页建立的目录。保证我们在查询时,可以通过二分法快速定位到页,再在页内通过二分法…...
Android Gradle Plugin Version 和 Gradle Version 的对应关系
官网参考 以下是插件版本和Gradle 版本对应关系: 插件版本所需的最低 Gradle 版本Android Gradle Plugin VersionGradle Version1.0.0 - 1.1.32.2.1 - 2.31.2.0 - 1.3.12.2.1 - 2.91.5.02.2.1 - 2.132.0.0 - 2.1.22.10 - 2.132.1.3 - 2.2.32.14.1 - 3.52.3.03.33.0…...
更多单词/词组/短语补充和总结(二)
auto 美 /[ˈɔːtoʊ] n.汽车adj.与汽车有关的,汽车的。不要记成“自动的” mobile 美 /[ˈmoʊbl] adj.可移动的;流动的;不要记成“手机”,手机是mobile phone automobile 美 /[ˈɔːtəməbiːl] n.汽车adj.自动的 automatic 美 /[ˌɔːtəˈmtɪk]…...
HEC-HMS和HEC-RAS快速入门、防洪评价报告编制及洪水建模、洪水危险性评价等应用
目录 ①HEC-RAS一维、二维建模方法及实践技术应用 ②HEC-HMS水文模型实践技术应用 ③新导则下的防洪评价报告编制方法及洪水建模实践技术应用 ④基于ArcGIS水文分析、HEC-RAS模拟技术在洪水危险性及风险评估 ⑤山洪径流过程模拟及洪水危险性评价 ①HEC-RAS一维、二维建模方…...
全面了解 B 端产品设计 — 基础扫盲篇
在今天,互联网的影响力与作用与日俱增,除了我们日常生活领域的改变以外,对于商业领域的渗透也见效颇丰。 越来越多的企业开始使用数字化的解决方案来助力企业发展,包括日常管理、运营、统计等等。或者通过互联网的方式开发出新的业务形态,进行产业升级,如这几年风头正劲的…...
顺序表(增删查改)
目录一、什么是顺序表二、顺序表的增删查改2.1 结构体的声明2.2 顺序表的初始化2.3 顺序表检查容量2.4 顺序表尾部插入数据2.5 顺序表头部插入数据2.6 顺序表尾部删除数据2.7 顺序表头部删除数据2.8 顺序表查找数据2.9 顺序表任意位置插入数据2.10 顺序表任意位置删除数据2.11 …...
一款优秀的低代码开发平台是什么样的?
目录 一、一款优秀的低代码平台应该是什么样的? 二、低代码核心能力 01、全栈可视化编程: 02、全生命周期管理: 03、低代码扩展能力: 三、小结 一、一款优秀的低代码平台应该是什么样的? 从企业角度来说&#x…...
ElasticSearch 学习笔记总结(四)
文章目录一、ES继承 Spring Data 框架二、SpringData 功能集成三、ES SpringData 文档搜索四、ES 优化 硬件选择五、ES 优化 分片策略六、ES 优化 路由选择七、ES 优化 写入速度优化七、ES 优化 内存设置八、ES 优化 重要配置一、ES继承 Spring Data 框架 Spring Data 是一个用…...
HDFS文件块大小
HDFS中的文件在物理上是分块存储(Block),块的大小可以通过配置参数(dfs.blocksize)来规定,默认大小在Hadooop2X版本中是128M,老版本中是64M。 思考:为什么块的大小不能设置太小&…...
C++——优先级队列(priority_queue)的使用及实现
目录 一.priority_queue的使用 1.1、基本介绍 1.2、优先级队列的定义 1.3、基本操作(常见接口的使用) 1.4、重写仿函数支持自定义数据类型 二.priority_queue的模拟实现 2.1、构造&&重要的调整算法 2.2、常见接口的实现 push() pop() top() empt…...
Linux学习记录——십일 环境变量
文章目录1、认识2、通过代码获取环境变量1、手动获取2、函数获取3、重新认识环境变量1、认识 在云服务器上写程序时,最终的执行需要./文件名,点表示当前目录,/是文件分隔符,之后就会打印程序,这是用户的操作ÿ…...
【人工智能 Open AI 】我们程序员真的要下岗了- 全能写Go / C / Java / C++ / Python / JS 人工智能机器人
文章目录[toc]人工智能 AI Code 写代码测试用golang实现冒泡排序用golang实现计算环比函数goroutine and channel用golang实现二叉树遍历代码用golang实现线程安全的HashMap操作代码using C programming language write a tiny Operation Systemuse C language write a tiny co…...
STM32 EXTI外部中断
本文代码使用 HAL 库。 文章目录前言一、什么是外部中断?二、外部中断中断线三、STM32F103的引脚复用四、相关函数:总结前言 一、什么是外部中断? 外部中断 是单片机实时地处理外部事件的一种内部机制。当某种外部事件发生时,单片…...
Mapper代理开发——书接MaBatis的简单使用
在这个mybatis的普通使用中依旧存在硬编码问题,虽然静态语句比原生jdbc都写更少了但是还是要写,Mapper就是用来解决原生方式中的硬编码还有简化后期执行SQL UserMapper是一个接口,里面有很多方法,都是一一和配置文件里面的sql语句的id名称所对…...
实体对象说明
1.工具类层Utilutil 工具顾明思义,util层就是存放工具类的地方,对于一些独立性很高的小功能,或重复性很高的代码片段,可以提取出来放到Util层中。2.数据层POJO对象(概念比较大) 包含了以下POJO plain ord…...
JAVA中加密与解密
BASE64加密/解密 Base64 编码会将字符串编码得到一个含有 A-Za-z0-9/ 的字符串。标准的 Base64 并不适合直接放在URL里传输,因为URL编码器会把标准 Base64 中的“/”和“”字符变为形如 “%XX” 的形式,而这些 “%” 号在存入数据库时还需要再进行转换&…...
改进YOLO系列 | ICLR2022 | OMNI-DIMENSIONAL DYNAMIC CONVOLUTION: 全维动态卷积
单个静态卷积核是现代卷积神经网络(CNNs)的常见训练范式。然而,最近的动态卷积研究表明,学习加权为其输入依赖注意力的n个卷积核的线性组合可以显著提高轻量级CNNs的准确性,同时保持高效的推理。然而,我们观察到现有的作品通过卷积核空间的一个维度(关于卷积核数量)赋予…...
信息收集之Github搜索语法
信息收集之Github搜索语法1.Github的搜索语法2.使用 Github 进行邮件配置信息收集3.使用Github进行数据库信息收集4.使用Github进行 SVN 信息收集5.使用Github进行综合信息收集在测试的信息收集阶段,可以去Github和码云上搜索与目标有关的信息,或者就有意…...
【案例教程】拉格朗日粒子扩散模式FLEXPART
拉格朗日粒子扩散模式FLEXPART通过计算点、线、面或体积源释放的大量粒子的轨迹,来描述示踪物在大气中长距离、中尺度的传输、扩散、干湿沉降和辐射衰减等过程。该模式既可以通过时间的前向运算来模拟示踪物由源区向周围的扩散,也可以通过后向运算来确定…...
试题 算法训练 自行车停放
问题描述 有n辆自行车依次来到停车棚,除了第一辆自行车外,每辆自行车都会恰好停放在已经在停车棚里的某辆自行车的左边或右边。(e.g.停车棚里已经有3辆自行车,从左到右编号为:3,5,1。现在编号为2的第4辆自行车要停在5号自行车的左…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
