MySQL索引——让查询飞起来
文章目录
- 索引是什么??
- 硬件理解
- MySQL与存储
- MySQL 与磁盘交互基本单位
- 索引的理解
- B+ vs B
- 聚簇索引 VS 非聚簇索引
- 索引操作
- 创建主键索引
- 唯一索引的创建
- 普通索引的创建
- 全文索引的创建
- 查询索引
- 删除索引
在现代数据库应用中,查询性能是决定系统响应速度和用户体验的关键因素之一。MySQL作为最流行的关系型数据库之一,提供了强大的索引功能来优化查询性能。本文将深入探讨MySQL索引的工作原理、类型以及如何通过索引优化查询,让你的数据库查询飞起来。
索引是什么??
对应文章标题:让查询飞起来
显然索引就能让加快查询速度
首先我们知道MySQL的服务器本质就是在内存中的,对于数据库的CRUD操作,全部是在内存中进行的!对于索引也是这样的;
我们在下面做一个测试
我们先创建一个数据库,里面填充一个名为EMP
的表,插入大量数据,我们发现耗时很久才插入完成
由于数据量太大,我们仅仅查看前十条
我们随便查询一条,发现时间好像有点久
这还是在本机一个人来操作,在实际项目中,如果放在公网中,假如同时有1000个人并发查询,那很可能就死机;
如何解决??
那就是本文所提到的索引;
- 解决方法,创建索引
当我们用下列SQL
语句,对原表的empo
列添加索引时,数据库底层就会为员工表中的数据记录构建特定的数据结构
alter table EMP add index(empno);
由于当前员工表中的数据量较大,因此建立索引时也需要花费较长时间
我们用同样的方法查询,可以看见时间非常短
原因:
常见的索引分为:
- 主键索引(primary key)
- 唯一索引(unique)
- 普通索引(index)
- 全文索引(fulltext)
硬件理解
MySQL与存储
MySQL 给用户提供存储服务,而存储的都是数据,数据在磁盘这个外设当中。磁盘是计算机中的一个机
械设备,相比于计算机其他电子元件,磁盘效率是比较低的。
我们看一个磁片,可以看到扇区的大小为512字节
那么在系统软件上 IO一定是512字节吗?
并不是
- 如果操作系统直接使用硬件提供的数据大小进行交互,那么如果硬件发生变化,系统必须跟着变;
- 而且单次访问512字节还是有点小,这样的话读取同样的内容,单次访问小也就意味着访问的次数需要提高,即效率降低;
磁盘随机访问(Random Access)与连续访问(Sequential Access)
- 随机访问:本次IO所给出的扇区地址和上次IO给出扇区地址不连续,这样的话磁头在两次IO操作之间需
要作比较大的移动动作才能重新开始读/写数据; - 连续访问:如果当次IO给出的扇区地址与上次IO结束的扇区地址是连续的,那磁头就能很快的开始这次
IO操作,这样的多个IO操作称为连续访问;
MySQL 与磁盘交互基本单位
而 MySQL 作为一款应用软件,可以想象成一种特殊的文件系统。它有着更高的IO场景,所以,为了提高
基本的IO效率, MySQL 进行IO的基本单位是 16KB
-
MySQL 中的数据文件,是以page为单位保存在磁盘当中的;
-
MySQL 的 CURD 操作,都需要通过计算,找到对应的插入位置,或者找到对应要修改或者查询的数据;
-
为了更高的效率,要尽可能的减少系统和磁盘IO的次数
索引的理解
为什么MySQL与磁盘交互的基本单位是Page
当我们要查询第一条内容时会进行一次IO,再次查询第三条内容时又会进行一次IO,此时已经IO两次;
但如果将其放在同一个Page下的话,查询第一条内容时,整个Page就会被放在缓冲池Buffer Pool中,后面再查询该Page中的内容时,就不用IO直接在Page中找,这样相当于只用了第一次查询的IO
我们无法保证下次要查询的内容在该Page中,但是由于局部性原理,很大概率下次的访问会在该Page中
- 局部性原理:大多数业务场景中,相邻数据(如同一表的连续记录)可能被同时访问
- 当需要某一行数据时,整个Page会被加载到内存,后续对同一Page内的数据访问无需再次触发磁盘I/O
理解单个Page
MySQL 中要管理很多数据表文件,而要管理好这些文件,就需要 先描述,在组织 ,我们目前可以简单理解
成一个个独立文件是有一个或者多个Page构成的
- 主键优化使数据的按序存储也是对查询的一种优化
- 正是因为有序,在查找的时候,从头到后都是有效查找,没有任何一个查找是浪费的
对于单个Page如果数据较多,线性遍历查找,对于最后一个数据来说并不友好;
所以我们在单个Page下创建一个目录,
也就是说对于1 2
条数据我们放在目录1
下,对于3 4
条数据放在目录2
下,也就是下图
- 这也就对应了上述所说,主键的有序也是一种优化,如果不是有序的话,目录下的内容是混乱的,此时效率非常低
- 随着数据量不断增大,单个Page中无法存下所有数据,这时就需要用多个Page来存储数据
- 这时在查询数据时就需要,先遍历Page双链表确定目标数据在哪一个Page,然后再在该Page内部找到目标数据
多个Page
随着数据量不断增大,单个Page中无法存下所有数据,这时就需要用多个Page来存储数据
- 在查询某条数据的时候直接将一整页的数据加载到内存中,以减少硬盘IO次数,从而提高性能
- 虽然在单个Page内部能够通过页内目录来快速定位数据,但在遍历Page双链表寻找目标Page时本质进行的还是线性遍历
- 这时可以给各个Page结构体也建立页目录,页目录中的每个目录项都指向一个Page,而这个目录项存放的就是其指向的Page中存放的最小数据的键值
- 在给各个Page结构体建立页目录后,在查询数据时就可以先通过遍历页目录找到目标数据所在的Page,然后再在该Page内部找到目标数据
所以我们给Page也带上目录
给Page也带上目录
- 目录页的本质也是页,普通页中存的数据是用户数据,而目录页中存的数据是普通页的地址
-
- 顶层的目录页少了,但是还要遍历啊
-
- 随着数据量不断增大,页目录的数量也会越来越多,这时在遍历页目录寻找目标Page时本质进行的还是线性遍历
结论:"套娃"——给目录页加一个目录
豁~~,这不就是B+树吗
这棵B+树就是InnoDB的索引结构
B+ vs B
B树
B+树
- | B树 | B+树 |
---|---|---|
数据存储位置 | 所有节点均可存储数据 | 仅叶子节点存储数据,内部节点为索引 |
叶子节点链接 | 无 | 叶子节点通过双向链表串联 |
树的高度 | 相对较高(相同数据量) | 相对较低 |
查询稳定性 | 可能在任何层级命中数据 | 必须查找到叶子节点 |
范围查询效率 | 低(需回溯父节点) | 高(链表直接遍历相邻叶子) |
冗余数据 | 无 | 键值在内部节点重复存储 |
适用场景 | 随机读写密集、数据离散访问 | 范围查询频繁、顺序扫描需求高 |
-
B树
- 每个节点(包括内部节点和叶子节点)均可存储数据
- 查询可能在任意层级终止(若命中内部节点)
-
B+树
- 仅叶子节点存储数据,内部节点仅存储键值作为索
- 叶子节点通过双向链表连接,支持高效顺序访问
- 所有查询必须走到叶子节点才能获取数据
查询性能
单次查询:B树更快,可能在内部节点提前命中
范围查询:B+树更快,通过叶子节点的链表直接遍历,无需回溯父节点,效率高
聚簇索引 VS 非聚簇索引
MyISAM 存储引擎-主键索引
MyISAM 引擎同样使用B+树作为索引结果,叶节点的data域存放的是数据记录的地址。下图为 MyISAM
表的主索引, Col1 为主键。
- 引Page和数据Page分离,也就是叶子节点没有数据,只有对应数据的地址
- MyISAM 这种用户数据与索引数据分离的索引方案,叫做非聚簇索引
- 所以, MyISAM 这种用户数据与索引数据分离的索引方案,叫做非聚簇索引
索引操作
创建主键索引
- 第一种方式
-- 在创建表的时候,直接在字段名后指定 primary key
create table user1(id int primary key, name varchar(30));
- 第二种方式
- 在创建表的最后,指定某列或某几列为主键索引
create table user2(id int, name varchar(30), primary key(id));
- 第三种方式
create table user3(id int, name varchar(30));
-- 创建表以后再添加主键
alter table user3 add primary key(id);
唯一索引的创建
- 第一种方式
-- 在表定义时,在某列后直接指定unique唯一属性。
create table user4(id int primary key, name varchar(30) unique);
- 第二种方式
-- 创建表时,在表的后面指定某列或某几列为unique
create table user5(id int primary key, name varchar(30), unique(name));
- 第三种方式
create table user6(id int primary key, name varchar(30));
alter table user6 add unique(name);
普通索引的创建
- 第一种方式
create table user8(id int primary key,name varchar(20),email varchar(30),index(name) --在表的定义最后,指定某列为索引
);
- 第二种方式
create table user9(id int primary key, name varchar(20), email varchar(30));
alter table user9 add index(name); --创建完表以后指定某列为普通索引
- 第三种方式
create table user10(id int primary key, name varchar(20), email varchar(30));
-- 创建一个索引名为 idx_name 的索引
create index idx_name on user10(name);
全文索引的创建
当对文章字段或有大量文字的字段进行检索时,会使用到全文索引
CREATE TABLE articles (id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,title VARCHAR(200),body TEXT,FULLTEXT (title,body)
)engine=MyISAM;
查询索引
- 第一种方法
show keys from 表名;
- 第二种方法
show index from 表名;
- 第三种方法
desc 表名;
删除索引
- 第一种方法,删除主键索引
alter table 表名 drop primary key;
- 第二种方法,其他索引的删除
alter table 表名 drop index 索引名;
- 第三种方法
drop index 索引名 on 表名;
索引创建原则
- 比较频繁作为查询条件的字段应该创建索引
- 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
- 更新非常频繁的字段不适合作创建索引
- 不会出现在where子句中的字段不该创建索引
相关文章:

MySQL索引——让查询飞起来
文章目录 索引是什么??硬件理解MySQL与存储 MySQL 与磁盘交互基本单位索引的理解B vs B聚簇索引 VS 非聚簇索引索引操作创建主键索引唯一索引的创建普通索引的创建全文索引的创建查询索引删除索引 在现代数据库应用中,查询性能是决定系统响应…...

Springboot集成Elasticsearch8.0(ES)版本,采用JAVA Client方式进行连接和实现CRUD操作
本文章介绍了 springboot t集成Elasticsearch8.0(ES)版本,如何通过 AVA Client方式进行连接和实现CRUD操作 在ES7.15版本之后,ES官方将高级客户端 RestHighLevelClient标记为弃用状态。同时推出了全新的 Java API客户端 Elasticsearch Java API Client,该客户端也将在 Ela…...

【Linux】APT 密钥管理迁移指南:有效解决 apt-key 弃用警告
引言 随着 Debian 11 和 Ubuntu 22.04 版本的推出,APT 的密钥管理方式发生了重大的变化。apt-key 命令被正式弃用,新的密钥管理机制要求使用 /etc/apt/keyrings/ 或 /etc/apt/trusted.gpg.d/ 来存储和管理密钥。这一变化对管理员和普通用户来说至关重要…...

洛谷P1143 进制转换
题目链接:P1143 进制转换 - 洛谷 | 计算机科学教育新生态 题目难度:普及— 解题思路:本题先将输入的数转为10进制,然后取模,最后倒着输出就好了,最后直接上代码 #include<bits/stdc.h> using namespa…...

99.12 金融难点通俗解释:毛利率
目录 0. 承前1. 简述2. 比喻:冰淇淋店赚钱2.1 第一步:准备材料2.2 第二步:卖冰淇淋2.3 第三步:计算毛利率 3. 生活中的例子3.1 好的毛利率3.2 一般的毛利率3.3 差的毛利率 4. 小朋友要注意4.1 毛利率高不一定好4.2 毛利率低不一定…...

HUMANITY’S LAST EXAM (HLE) 综述:人工智能领域的“最终考试”
论文地址:Humanity’s Last Exam 1. 背景与动机 随着大型语言模型(LLMs)能力的飞速发展,其在数学、编程、生物等领域的任务表现已超越人类。为了系统地衡量这些能力,LLMs 需要接受基准测试(Benchmarks&…...

C++从入门到实战(二)C++命名空间
C从入门到实战(二)C命名空间 前言一、C的第一个程序二、命名空间(一)为什么需要命名空间(二)定义命名空间(三)使用命名空间1.通过命名空间限定符:2.使用 using 声明&…...

C# OpenCV机器视觉:实现农作物病害检测
在酷热难耐的夏日,阳光似火舌般舔舐大地。阿强惬意地躺在老家院子摇椅上,哼着小曲,手边放着一碗冰镇西瓜,头顶大槐树宛如巨大遮阳伞,洒下斑驳阴凉。他本想趁假期回老家放松,远离城市喧嚣与代码 “纠缠”。 …...

开源软件协议介绍
一、可以闭源使用/不具传染性的协议 允许商业使用和分发 1、BSD:详细介绍 2、LGPL许可证:详细介绍 3、MPL2.0:详细介绍 二、具有传染性/使用后需要开源自身软件的协议 不建议商业使用 1、GPL许可证:详细介绍...

CLion开发Qt桌面
IDE:CLion Qt Qt版本:5.12 学习正点原子的嵌入式Linux开发板时,使用Qt Creator写代码不是很方便,遂尝试使用CLion搭建Qt开发环境。 一、CLion的Qt环境搭建 1,配置工具链 找到Qt的安装目录,此处为E:\Tools\…...

09_异步加载_单例模式_常量类配置_不可销毁
1.首先在 资源加载服务层ResSvc.cs中添加 自定义异步加载函数 using UnityEngine; using UnityEngine.SceneManagement; //异步加载 命名空间 //功能 : 资源加载服务 public class ResSvc : MonoBehaviour{public void InitSvc(){Debug.Log("Init ResSvc...");}//自定…...

士的宁(strychnine)的生物合成-文献精读104
Biosynthesis of strychnine 士的宁(strychnine) 又名 番木鳖碱 的生物合成 摘要 士的宁(番木鳖碱)是一种天然产物,通过分离、结构阐明和合成努力,塑造了有机化学领域。目前,士的宁因其强大的…...

【开源免费】基于Vue和SpringBoot的常规应急物资管理系统(附论文)
本文项目编号 T 159 ,文末自助获取源码 \color{red}{T159,文末自助获取源码} T159,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...

(Java版本)基于JAVA的网络通讯系统设计与实现-毕业设计
源码 论文 下载地址: cc基于JAVA的网络通讯系统设计与实现(源码系统论文)https://download.csdn.net/download/weixin_39682092/90299782https://download.csdn.net/download/weixin_39682092/90299782 第1章 绪论 1.1 课题选择的…...

ray.rllib 入门实践-2:配置算法
前言: ray.rllib的算法配置方式有多种,网上的不同教程各不相同,有的互不兼容,本文汇总罗列了多种算法配置方式,给出推荐,并在最后给出可运行代码。 四种配置方式 方法1 import os from ray.rllib.algori…...

2025-01学习笔记
1.SpEL 第一次知道它的全称 Spring Expression Language(SpEL) Value("${my.property}") private String myProperty; Value("#{2 * 3}") private int computedValue; 2.逃逸分析 逃逸分析:当一个对象在方法中被定…...

多线程执行大批量数据查询
// 创建一个固定大小的线程池ExecutorService executorService Executors.newFixedThreadPool(5);// 创建多个查询任务List<Callable<List<ShopCompareBase>>> tasks new ArrayList<>();//查询门店 切割,分成十份List<List<String>> sho…...

ChatGPT高效处理图片技巧使用详解
ChatGPT,作为OpenAI开发的预训练语言模型,主要用于生成自然语言文本的任务。然而,通过一些技巧和策略,我们可以将ChatGPT与图像处理模型结合,实现一定程度上的图像优化和处理。本文将详细介绍如何使用ChatGPT高效处理图…...

leetcode——相交链表(java)
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意,函数返回结果后&…...

RubyFPV开源代码之系统简介
RubyFPV开源代码之系统简介 1. 源由2. 工程架构3. 特性介绍(软件)3.1 特性亮点3.2 数字优势3.3 使用功能 4. DEMO推荐(硬件)4.1 天空端4.2 地面端4.3 按键硬件Raspberry PiRadxa 3W/E/C 5. 软件设计6. 参考资料 1. 源由 RubyFPV以…...

麦田物语学习笔记:创建TransitionManager控制人物场景切换
基本流程 制作场景之间的切换 1.代码思路 (1)为了实现不同场景切换,并且保持当前的persistentScene一直存在,则需要一个Manager去控制场景的加载和卸载,并且在加载每一个场景之后,都要将当前的场景Set Active Scene,保证其为激活的场景,在卸载的时候也可以方便调用当前激活的场…...

后端SpringBoot学习项目-用户管理-增删改查-service层
仓库地址 在初版代码中,已经实现了基础的增删改查。 但是,逻辑处理都放在Controller层中并没有分为Service层,所以,代码升级时候必须补充上去。 代码结构 升级后的代码结构有所变化。 --common 公共插件 --controller…...

机器学习11-学习路径推荐
机器学习11-学习路径推荐 本文希望摒除AI学习商业宣传要素,推荐一条极简的AI学习路线!推荐内容均为在线免费内容,如果有条件可以咨询专业的培训机构! 文章目录 机器学习11-学习路径推荐[toc] 1-AI培训路线第一阶段 Python-人工智能…...

[ACTF2020 新生赛]Upload1
题目 以为是前端验证,试了一下PHP传不上去 可以创建一个1.phtml文件。对.phtml文件的解释: 是一个嵌入了PHP脚本的html页面。将以下代码写入该文件中 <script languagephp>eval($_POST[md]);</script><script languagephp>system(cat /flag);&l…...

【PyTorch】0.初识:从吃货角度理解张量
0.初识张量 PyTorch 是一个 Python 深度学习框架,它将数据封装成张量(Tensor)来进行运算。PyTorch 中的张量就是元素为同一种数据类型的多维矩阵。在 PyTorch 中,张量以 "类" 的形式封装起来,对张量的一些运…...

医学图像分析工具09.1:Brainstorm安装教程
1. 安装前准备 **官方安装包和数据:**https://neuroimage.usc.edu/bst/download.php **官方安装教程:**https://neuroimage.usc.edu/brainstorm/Installation Matlab 版本要求: 有 Matlab: R2009b (7.9) 或更高版本没有 Matlab&…...

springboot基于Spring Boot的智慧养老服务系统的设计与实现
系统介绍: 智慧养老服务系统是一种运用现代科技手段,整合各类养老资源,为老年人提供全方位、个性化服务的综合性平台。该系统通过智能化设备、大数据分析、云计算等技术,实现对老年人健康状况、生活需求的实时监控与精准匹配&…...

Linux内核中IPoIB驱动模块的初始化与实现
InfiniBand(IB)是一种高性能的网络互连技术,广泛应用于高性能计算(HPC)和数据中心。为了在InfiniBand网络上运行标准的IP协议栈,Linux内核提供了IP over InfiniBand(IPoIB)驱动模块。IPoIB允许在InfiniBand网络上传输IPv4和IPv6数据包,从而使得现有的IP应用程序能够无…...

WPS计算机二级•幻灯片的基础操作
听说这是目录哦 PPT的正确制作步骤🛣️认识PPT界面布局🏜️PPT基础操作 快捷键🏞️制作PPT时 常用的快捷技巧🏙️快速替换PPT的 文本字体🌃快速替换PPT 指定文本内容🌅能量站😚 PPT的正确制作步…...

.NET9增强OpenAPI规范,不再内置swagger
ASP.NETCore in .NET 9.0 OpenAPI官方文档ASP.NET Core API 应用中的 OpenAPI 支持概述 | Microsoft Learnhttps://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/openapi/overview?viewaspnetcore-9.0https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/ope…...