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以…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...