【MySQL】索引 详解
索引 详解
- 一. 概念
- 二. 作用
- 三. 使用场景
- 四. 操作
- 五. 索引背后的数据结构
- B-树
- B+树
- 聚簇索引与非聚簇索引
一. 概念
索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。
二. 作用
数据库中的表、数据、索引之间的关系,类似于书架上的图书、书籍内容和书籍目录的关系。索引所起的作用类似书籍目录,可用于快速定位、检索数据,对于提高数据库的性能有很大的帮助。

作用:提高查找效率
代价:
- 占用更多空间:数据库索引需要消耗一定的额外空间, 数据量越大, 索引消耗的额外空间越多。
- 拖慢增删改的效率:当进行增删改时, 往往需要同步调整索引结构
三. 使用场景
要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:
- 数据量较大,且经常对这些列进行条件查询。
- 该数据库表的插入操作,及对这些列的修改操作频率较低。
- 索引会占用额外的磁盘空间。
满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。
反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。
四. 操作
创建主键约束(PRIMARY KEY)、唯一约束(UNIQUE)、外键约束(FOREIGN KEY)时,会自动创建对应列的索引。
- 查看索引
show index from 表名;
示例:查看学生表已有的索引
show index from student;
- 创建索引
对于非主键、非唯一约束、非外键的字段,可以创建普通索引
create index 索引名 on 表名(字段名);
示例:创建班级表中,name字段的索引
create index idx_classes_name on classes(name);
注意:
创建索引是一个非常低效的操作, 尤其是当表中已经有很多数据时, 不能贸然创建索引。
- 删除索引
drop index 索引名 on 表名;
示例:删除班级表中name字段的索引
drop index idx_classes_name on classes;
同理, 删除索引也是非常低效的, 容易把数据库搞崩。
所以,在创建表的时候,就应该把索引建好。
五. 索引背后的数据结构
- 为什么顺序表按下标访问速度就快呢 ?为什么不能用 顺序表 存索引呢 ?
顺序表是在 内存 空间中连续存储, 所以支持随机访问,(访问任意地址上的数据速度都是极快的),这是因为内存的硬件结构所支持的。
虽然快, 但是索引是存储在硬盘上的。
- 二叉搜索树为什么不适合做索引 ?
二叉搜索树, 查找时间复杂度为 O(N)(最坏情况 -> 单分支树),
那么就不让二叉搜索树变成单分支树 :
- AVL树:平衡二叉搜索树,要求任意节点左右子树的高度差不超过 1
- 红黑树:要求比 AVL 树更宽松一点的平衡二叉树
它们都不太适合做索引:
二叉树最大的问题就是当元素多了, 高度就高了, 高度就对应着比较次数,对于数据库来说,每次比较意味着磁盘 IO 。
- 为什么哈希表也不适合存储索引 ?
虽然哈希表查找速度很快,时间复杂度为 O(1),但是哈希表只能针对 “相等” 进行判定,不能对于 “大于”、 “小于” 以及范围查找进行判定,也不能进行模糊匹配(因为哈希表是根据 key 值找到 value 的)。
- 堆更不适合:
- 是二叉树
- 堆只能找到最大值 / 最小值
- 最适合做索引的还得是树形结构, 只不过不是二叉树。
使用多叉搜索树,高度自然就下降了。
数据库中使用的这个多叉搜索树, 是很特殊的树称为 B+ 树。
B-树
(不读作 B 减 树, 这个 - 是连字符, 它就是 B 树)
B 树: 每个节点上都存储 N 个 key 值, N 个 key 值分成 N+1 个区间,每个区间对应一个子树

可以简单理解为下图这个例子:

查找过程:
和二叉搜索树类似, 先从根出发, 根据待比较元素, 确定一个区间。
- 在确定区间时不是也需要比较多次嘛 ? 和二叉搜索树相比有什么优势 ?
二叉搜索树,每个节点上面只有一个值, 只比较一次,比较次数和高度相关。
但是 B-树, 高度降低了, 只不过每个节点比较了多次, 但是相比于比较次数来说,IO 次数才是关键的, 磁盘是以节点为单位进行 IO 的,每次 IO 加载一个节点, 但是 B-树每个节点中好几个值, B-树高度低很多, IO 次数更少, 效率更高。
B+树
(这个确实就读作 B加 树)

B+ 树: 也是一棵 N 叉搜索树,每个节点上包含多个 key 值, 每个节点若有 N 个 key, 分成 N 个区间 (而不是 N+1 个)
关键点:
- 父节点的值都会在子节点中体现。
- 非叶子节点中的每个值最终都会在叶子节点中体现出来。
- 父节点中的值会作为子节点中的最大值/最小值 (上图以最小值为例)。
- 最下面的叶子节点,用链表进行按顺序连接。
- 非叶子节点只存储 key 值本身即可,叶子节点是完整的数据集合, 只在叶子节点存储数据表的每一行数据。
B+ 树就是为了数据库索引量身打造的:
- 使用 B+ 树进行查找时,整体的 IO 次数比较少。
- 所有查询最终都会落到叶子节点, 每次查询的 IO 次数都差不多, 查询次数稳定,效率就比较稳定。
- 叶子节点用链表相连, 非常适合范围查找,例如查找 ( 30 <= x <= 85) 的值。
- 所有的数据存储(载荷)都是放到叶子节点, 非叶子节点中只保存 key 即可,因此非叶子节点整体占用的空间较小, 甚至可以缓存到内存中,一旦能放到内存中了,磁盘 IO 几乎就没有了。
聚簇索引与非聚簇索引

聚簇索引:
- 将索引与数据放到一块了(指叶子节点),找到索引也就找到数据了。
所以一个表中只能有一个聚簇索引。(因为只有一份数据。) - 聚簇索引将索引值相同的数据放一块。
- 使用二级索引时, 先通过二级索引找到主键索引,再通过主键索引中找数据。(这个过程称为 “回表”)
比如使用 id 建一个索引, 再使用 name 建一个索引, 那么 name 这个索引中叶子节点最终存储的是 id, 然后再通过 id 找到对应的 数据。
为什么辅助索引不直接存储数据的位置?
因为这样就算数据的位置变了,二级索引也不用变。因为对应的主键索引并没有变。 - 聚簇索引中, 数据的物理存放顺序与索引的顺序完全相同,索引相邻,那么对应的数据在磁盘上的位置一定也相邻。所以数据地址都是挨着的。
意味着:如果说, 你插入的这条数据对应的索引不是递增的, 那么这个索引就要插入到中间位置,也就是说对应的数据也要插入中间位置, 也就是说需要挪动数据,才能将这条数据及其索引插入进去。更改了索引结构,大大降低了 更新/插入数据的效率。
所以说:一般以自增主键作为聚簇索引,这样每次插入数据都是添加到末尾, 不用挪动数据。
非聚簇索引:
- 叶子节点中存储的时数据的位置, 而不是数据本身。
- 通过主键索引和二级索引都能直接找到数据, 两者几乎没有区别, 只是一个存储主键, 另一个存储辅助键。
- 数据存放的地址是凌乱的。所以更新/插入数据的速度一般比聚簇索引快,因为只要开辟一块空间把数据放进去就行了,然后让索引中记录位置就行了,不用考虑数据存放的位置。
两者最重要的区别就是:
- 聚簇索引的数据与索引放到一起。(指叶子节点。)
- 聚簇索引中数据存放的物理顺序与索引的排序完全相同。
好啦! 以上就是对 MySQL 索引的讲解, 希望能帮到你 !
评论区欢迎指正 !
相关文章:
【MySQL】索引 详解
索引 详解 一. 概念二. 作用三. 使用场景四. 操作五. 索引背后的数据结构B-树B树聚簇索引与非聚簇索引 一. 概念 索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各…...
怎么通过ip地址连接共享打印机
在现代办公环境中,共享打印机已成为一种常见的需求。通过共享打印机,多个用户可以在网络上共享同一台打印机,从而提高工作效率并减少设备成本。下面虎观代理小二二将介绍如何通过IP地址连接共享打印机。 确定打印机的IP地址 首先࿰…...
迅为i.MX8mm小尺寸商业级/工业级核心板
尺寸: 50mm*50mm CPU: NXP i.MX8M Mini 主频: 1.8GHz 架构: 四核Cortex-A53,单核Cortex-M4 PMIC: PCA9450A电源管理PCA9450A电源管理NXP全新研制配,iMX8M的电源管理芯片有六个降压稳压器、五…...
vue中v-for循环数组使用方法中splice删除数组元素(错误:每次都删掉点击的下面的一项)
总结:平常使用v-for的key都是使用index,这里vue官方文档也不推荐,这个时候就出问题了,我们需要key为唯一标识,这里我使用了时间戳(new Date().getTime())处理比较复杂的情况, 本文章…...
Python用GAN生成对抗性神经网络判别模型拟合多维数组、分类识别手写数字图像可视化...
全文链接:https://tecdat.cn/?p33566 生成对抗网络(GAN)是一种神经网络,可以生成类似于人类产生的材料,如图像、音乐、语音或文本(点击文末“阅读原文”获取完整代码数据)。 相关视频 最近我们…...
嵌入式Linux驱动开发(LCD屏幕专题)(一)
一、LCD简介 总的分辨率是 yres*xres。 1.1、像素颜色的表示 以下三种方式表示颜色 1.2、如何将颜色数据发送给屏幕 每个屏幕都有一个内存(framebuffer)如下图,内存中每块数据对用屏幕上的一个像素点,设置好LCD后ÿ…...
uniapp搜索功能
假设下方数据是我们从接口中获取到的,我们需要通过name来搜索,好我们看下一步。 data: [{"id": 30,"category_id": 3,"name": "日常家居名称","goods_num": 20,"integral_num": 20,&q…...
iframe 实现跨域,两页面之间的通信
一、 背景 一个项目为vue2,一个项目为vue3,两个不同的项目实现iframe嵌入,并实现通信 二、方案 iframe跨域时,iframe组件之间常用的通信,主要是H5的possmessage方法 三、案例代码 父页面-vue2(端口号为…...
DevOps到底是什么意思?
前言: 当我们谈到 DevOps 时,可能讨论的是:流程和管理,运维和自动化,架构和服务,以及文化和组织等等概念。那么,到底什么是"DevOps"呢? 那么,DevOps是什么呢? 有人说它是一种方法,也有人说它是一种工具,还有人说它是一种思想。更有甚者,说它是一种哲学…...
03JVM_类加载
一、类加载与字节码技术 1.类文件结构 2.字节码指令 3.编译期处理 4.类加载阶段 5.类加载器 6.运行期优化 1.类文件结构 类文件结构 1.1 魔数magic 介绍 每个java class文件的前4个字节是魔数:0x CAFEBABE。魔数作用在于分辨出java class文件和非java clas…...
Mysql如何对null进行排序(mysql中null排序)
来源:Mysql如何对null进行排序(mysql中null排序) Mysql如何对null进行排序 Mysql是一种开源的关系型数据库管理系统,经常被用于Web开发和应用程序中。在使用Mysql进行数据处理的过程中,很多时候都会遇到需要对null进行…...
【基础计算机网络1】认识计算机网络体系结构,了解计算机网络的大致模型(下)
前言 在上一篇我们主要介绍了有关计算机网络概述的内容,下面这一篇我们将来介绍有关计算机网络体系结构与参考模型的内容。这一篇博客紧紧联系上一篇博客。 这一篇博客主要内容是:计算机网络体系结构与参考模型,主要是计算机网络分层结构、协…...
vscode 画流程图
文章目录 1、安装插件 draw2、新建文件3、开始画图4、另存为图片 vscode可以画流程图了,只需要安装插件就可以了。 1、安装插件 draw 2、新建文件 3、开始画图 4、另存为图片...
uniapp-一些实用的api接口
唤起导航 调用后可以跳转到地图页 uni.openLocation({latitude: res.data.data.latitude, //到达的纬度longitude: res.data.data.longitude, //到达的经度name: res.data.data.address, // 到达的名字scale: 12, // 缩放倍数success() { // 成功回调console.log(success) }…...
合宙Air724UG LuatOS-Air LVGL API控件-表格(Table)
表格(Table) 示例代码 --创建表格Table1 lvgl.table_create(lvgl.scr_act(),nil)--设置表格为4行5列lvgl.table_set_row_cnt(Table1,4)lvgl.table_set_col_cnt(Table1,5)--给每个单元格赋值lvgl.table_set_cell_value(Table1, 0, 0, "选手")l…...
前缀和思想
何为前缀和 有一个数组a, 为 ...... 前缀和 ...... 有两个问题: 1.如何求? 只需要从前往后遍历,令 就可以了,最开始是 ,定义 0 2. 有什么用? 能够快速地求出原数组中某一段的和,预处理的…...
Llama2-Chinese项目:1-项目介绍和模型推理
Atom-7B与Llama2间的关系:Atom-7B是基于Llama2进行中文预训练的开源大模型。为什么叫原子呢?因为原子生万物,Llama中文社区希望原子大模型未来可以成为构建AI世界的基础单位。目前社区发布了6个模型,如下所示: FlagAl…...
论文于祥读及复现——《VDO-SLAM: A Visual Dynamic Object-aware SLAM System》
论文详读之------《一个视觉动态对象感知SLAM系统》 0. 出发点(暨摘要)1.引言2. 相关工作2.1 探索针对动态环境的健壮SLAM2.2 分别执行SLAM和运动对象跟踪(MOT),作为传统SLAM的扩展,用于动态场景理解。2.3 对象SLAM(通…...
nuxt3项目使用pdfjs-dist预览pdf
使用的包的源代码是 pdfjs - npm 但是我们实际上项目中使用的是pdfjs打包后的dist文件,也就是pdfjs-dist - npm 所以我们需要使用这个命令 npm i pdfjs-dist 我们可以克隆pdfjs这个包来看源代码,里面有使用的例子,也可以根据源代码自己打…...
mybatis-generator-maven-plugin使用
前提说明 数据库:MYSQL57Mybatis : http://mybatis.org/generator/index.html 操作说明 引入插件 <plugins><!-- MyBatis 逆向工程 插件 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generat…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
