MySQL索引详解(IT枫斗者)

news2025/1/11 10:48:46

MySQL索引详解

什么是索引

  • 官方介绍索引是帮助MySQL高效获取数据数据结构。简单来讲,数据库索引就像是书前面的目录,能加快数据库的查询速度
  • 事实上,索引是一种数据结构,用于帮助我们在大量数据中快速定位到我们想要查找的数据。
  • 但对于海量数据来说,它的目录也是很大的,不可能全部存储在内存中,因此索引往往是存储在磁盘上的文件中(可能存储在单独的索引文件中,也可能和数据一起存储在数据文件中)。

索引的分类

单列索引

  • 一个索引只包含单个列,但一个表中可以有多个单列索引。 这里不要搞混淆了
  • 普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一 点。
  • 唯一索引:索引列中的值必须是唯一的,但是允许为空值。
  • 主键索引:是一种特殊的唯一索引,不允许有空值。(主键约束,就是一个主键索引)。

组合索引

  • 在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。

全文索引

  • 全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引,介绍了要求,说说什么是全文索引,就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行。

索引的数据结构

  • 索引的数据结构使用的是B+树,那为什么使用B+树而不是二叉查找树、平衡二叉树或者B树呢,接下来,我们来讲讲B+树的由来。

二叉查找树

  • 首先,我们来讲讲二叉查找树

  • 二叉查找树有这样的特点:

    • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    • 它的左、右子树也分别为二叉查找树。
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NL7Fq7w3-1684801364672)(C:\Users\quyanliang\AppData\Roaming\Typora\typora-user-images\1684801078099.png)]

  • 二叉查找树的特点就是为了保证每次查找都可以这折半而减少IO次数,但是二叉树就很考验第一个根节点的取值,因为很容易在这个特点下出现我们并发想发生的情况“树不分叉了”,这是我们不想见到的。

二叉平衡树

  • 平衡二叉树是采用二分法思维,平衡二叉查找树除了具备二叉树的特点,最主要的特征是树的左右两个子树的层级最多相差1。在插入删除数据时通过左旋/右旋操作保持二叉树的平衡,不会出现左子树很高、右子树很矮的情况。

  • 使用平衡二叉查找树查询的性能接近于二分查找法,时间复杂度是 O(log2n)。查询id=6,只需要两次IO。

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d3W2AuUo-1684801364673)(C:\Users\quyanliang\AppData\Roaming\Typora\typora-user-images\1684801122286.png)]

  • 就这个特点来看,可能各位会觉得这就很好,可以达到二叉树的理想的情况了。然而依然存在一些问题:

  • 时间复杂度和树高相关。树有多高就需要检索多少次,每个节点的读取,都对应一次磁盘 IO 操作。树的高度就等于每次查询数据时磁盘 IO 操作的次数。磁盘每次寻道时间为10ms,在表数据量大时,查询性能就会很差。(1百万的数据量,log2n约等于20次磁盘IO,时间20*10=0.2s)

  • 平衡二叉树不支持范围查询快速查找,范围查询时需要从根节点多次遍历,查询效率不高。

B树:改造二叉平衡树

  • 对于二叉平衡树,我们更希望出现‘矮胖’树而不是‘瘦高’树,因为这样可以减少查询时的IO操作次数,增加查询效率。那么我们如何能够降低树的高度呢?

  • 假如key为bigint=8字节,每个节点有两个指针,每个指针为4个字节,一个节点占用的空间16个字节(8+42=16)

  • 因为在MySQL的InnoDB存储引擎一次IO会读取的一页(默认一页16K)的数据量,而二叉树一次IO有效数据量只有16字节,空间利用率极低。为了最大化利用一次IO空间,一个简单的想法是在每个节点存储多个元素,在每个节点尽可能多的存储数据。每个节点可以存储1000个索引(16k/16=1000),这样就将二叉树改造成了多叉树,通过增加树的叉树,将树从高瘦变为矮胖。构建1百万条数据,树的高度只需要2层就可以(10001000=1百万),也就是说只需要2次磁盘IO就可以查询到数据。磁盘IO次数变少了,查询数据的效率也就提高了。

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FeSr554P-1684801364674)(C:\Users\quyanliang\AppData\Roaming\Typora\typora-user-images\1684801175305.png)]

  • 这种数据结构我们称为B树,B树是一种多叉平衡查找树,主要特点如下:

    1. B树的节点中存储着多个元素,每个内节点有多个分叉。
    2. 节点中的元素包含键值和数据,节点中的键值从大到小排列。也就是说,在所有的节点都储存数据。
    3. 父节点当中的元素不会出现在子节点中。
    4. 所有的叶子结点都位于同一层,叶节点具有相同的深度,叶节点之间没有指针连接。
  • 到这里,B树已经是比较理想的了,但我们还有可以优化的地方:

  • B树不支持范围查询的快速查找,你想想这么一个情况如果我们想要查找10和35之间的数据,查找到15之后,需要回到根节点重新遍历查找,需要从根节点进行多次遍历,查询效率有待提高。

  • 如果data存储的是行记录,行的大小随着列数的增多,所占空间会变大。这时,一个页中可存储的数据量就会变少,树相应就会变高,磁盘IO次数就会变大。

B+树:改造B树

  • B+树,作为B树的升级版,在B树基础上,MySQL在B树的基础上继续改造,使用B+树构建索引。B+树和B树最主要的区别在于非叶子节点是否存储数据的问题

  • B树:非叶子节点和叶子节点都会存储数据。

  • B+树:只有叶子节点才会存储数据,非叶子节点至存储键值。叶子节点之间使用双向指针连接,最底层的叶子节点形成了一个双向有序链表。

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5oQ5DB2X-1684801364674)(C:\Users\quyanliang\AppData\Roaming\Typora\typora-user-images\1684801238898.png)]

  • B+树的最底层叶子节点包含了所有的索引项。从图上可以看到,B+树在查找数据的时候,由于数据都存放在最底层的叶子节点上,所以每次查找都需要检索到叶子节点才能查询到数据。所以在需要查询数据的情况下每次的磁盘的IO跟树高有直接的关系,但是从另一方面来说,由于数据都被放到了叶子节点,所以放索引的磁盘块锁存放的索引数量是会跟这增加的,所以相对于B树来说,B+树的树高理论上情况下是比B树要矮的。也存在索引覆盖查询的情况,在索引中数据满足了当前查询语句所需要的全部数据,此时只需要找到索引即可立刻返回,不需要检索到最底层的叶子节点。

MySQL索引的优化

避免回表

  • 在InnoDB的存储引擎中,使用辅助索引查询的时候,因为辅助索引叶子节点保存的数据不是当前记录的数据而是当前记录的主键索引,索引如果需要获取当前记录完整数据就必然需要根据主键值从主键索引继续查询。这个过程我们成位回表。想想回表必然是会消耗性能影响性能。那如何避免呢?
  • 使用索引覆盖,举个例子:现有User表(id(PK),name(key),sex,address,hobby…)
  • 如果在一个场景下,select id,name,sex from user where name =‘zhangsan’;这个语句在业务上频繁使用到,而user表的其他字段使用频率远低于它,在这种情况下,如果我们在建立 name 字段的索引的时候,不是使用单一索引,而是使用联合索引(name,sex)这样的话再执行这个查询语句是不是根据辅助索引查询到的结果就可以获取当前语句的完整数据。这样就可以有效地避免了回表再获取sex的数据。
  • 这就是一个典型的使用覆盖索引的优化策略减少回表的情况。

联合索引的使用

  • 联合索引,在建立索引的时候,尽量在多个单列索引上判断下是否可以使用联合索引。联合索引的使用不仅可以节省空间,还可以更容易的使用到索引覆盖。试想一下,索引的字段越多,是不是更容易满足查询需要返回的数据呢。比如联合索引(a_b_c),是不是等于有了索引:a,a_b,a_b_c三个索引,这样是不是节省了空间,当然节省的空间并不是三倍于(a,a_b,a_b_c)三个索引,因为索引树的数据没变,但是索引data字段的数据确实真实的节省了。
  • 联合索引的创建原则,在创建联合索引的时候因该把频繁使用的列、区分度高的列放在前面,频繁使用代表索引利用率高,区分度高代表筛选粒度大,这些都是在索引创建的需要考虑到的优化场景,也可以在常需要作为查询返回的字段上增加到联合索引中,如果在联合索引上增加一个字段而使用到了覆盖索引,那建议这种情况下使用联合索引。
  • 联合索引的使用:
  • 考虑当前是否已经存在多个可以合并的单列索引,如果有,那么将当前多个单列索引创建为一个联合索引。
  • 当前索引存在频繁使用作为返回字段的列,这个时候就可以考虑当前列是否可以加入到当前已经存在索引上,使其查询语句可以使用到覆盖索引。
  • 种草链接 : 学习或者部署项目需要云产品,枫哥给大家申请到福利,现有64款云产品免费试用:https://click.aliyun.com/m/1000371850/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/561506.html

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

相关文章

chatgpt赋能Python-python_pyyaml

Python与PYAML的SEO 介绍 在当今以数据为中心的时代,数据的存储、传输和处理出现了许多新的挑战。Python作为一门强大的编程语言,已经成为数据处理的利器。而PYAML则是Python中一款重要的yaml库。 YAML与PYAML YAML(YAML Ain’t Markup L…

语法速通 uni-app随笔【uni-app】【微信小程序】【vue】

1、微信小程序 1.1、wx 小程序 工程目录 其中, pages目录/index目录【必有】: index.js 编写业务逻辑 【初始数据,生命周期函数】 index.json 编写配置 index.wxml 编写模板 【可理解为本页html】 index.wxss 【可理解为本页css】 1.2、wx…

The Development of DBMS in History--人工翻译

导言 数据库类型 ,有时称为数据库模型或数据库族,是用于在数据库管理系统内组织数据的模式和结构。多年来已经开发了许多不同的数据库类型。一些主要是当前数据库的历史前辈,而另一些则经受住了时间的考验。在过去的几十年中,新的…

chatgpt赋能Python-python_plot散点图

Python Plot散点图:详细介绍与使用教程 Python是一种广泛使用的编程语言,特别适合处理数据科学任务。Python有大量的用于数据可视化的库,其中matplotlib是最重要的之一。在本文中,我们将探讨matplotlib中的散点图plot&#xff0c…

[ 云计算 Azure ] Chapter 07 | Azure 网络服务中的虚拟网络 VNet、网关、负载均衡器 Load Balancer

本系列已经更新文章列表(已更新): [ Azure 云计算从业者 ] Chapter 03 | 描述云计算运营中的 CapEx 与 OpEx,如何区分 CapEx 与 OpEx[ Azure 云计算从业者 ] Chapter 04 | Azure核心体系结构组件之数据中心、区域与区域对、可用区…

什么是智能合约存储布局?

本指南将解释智能合约中存储的数据。合约存储布局是指控制合约存储变量在长期内存中排布的规则。 读者先决条件知识 以下一般先决条件有助于理解本文: 熟悉面向对象的语言 位和字节 十六进制 智能合约 以太坊虚拟机(EVM) 哈希 无符号整数 静态…

图像噪声类别

什么是图像噪声? 图像噪声是图像在获取或是传输过程中受到随机信号干扰,妨碍人们对图像理解及分析处理 的信号。 图像噪声的产生来自图像获取中的环境条件和传感元器件自身的质量,图像在传输过程中产 生图像噪声的主要因素是所用的传输信道…

chatgpt赋能Python-python_quad

Python quad是什么? 在Python编程中,Quad是指四元组的缩写。它是一个包含四个元素的有序组。Quad通常在图形学和计算机图像处理中广泛应用。 在Quad中,每个元素都可以是数字或点的组合。 在Python编程中,quad被广泛用于三维计算机…

我最近的练习一些全栈项目

嘿,大家好!作为一个程序员,我突然出现在这里,就像程序里的一个Bug一样突兀。我知道我很久没有发博客了,你们一定在想,这家伙是被代码迷宫困住了还是被Bug们抓走了?实际上,我一直忙于…

一文读懂:什么是数组

大家好,我是三叔,很高兴这期又和大家见面了,一个奋斗在互联网的打工人。 什么是数组 Java是一种面向对象的编程语言,提供了许多数据结构来处理和组织数据。其中,数组是一种常见且强大的数据结构,是存放在…

python+mysql电影推荐系统 影院售票选座系统vue

随着互联网的蓬勃发展,现代社会进入了以计算机为中心的信息时代,计算机技术正以一种前所未有的持久方式改变着世界的面貌。应用网络技术电影推荐系统受到许多用户的重视。网站的开发可以对人们的交流起到重要的作用,因此,为了满足…

印象笔记导出HTML再转markdown的方法

前言 我已经使用6年印象笔记了,越来越依赖它了,现在已经有6000多条笔记了,我就想着如果某一天印象笔记没了,那我这些心血就都没了,所以我想要把笔记全部转为markdown格式,然后自己存储起来。可以选择用百度…

chatgpt赋能Python-python_pendulum

Python Pendulum: 了解更便捷的时间操作 在我们的日常生活中,对于时间的操作极为频繁,不仅仅是时钟和日历,还包括计划、调度等等。Python pendulum正是一个极为优秀的工具,它为我们的时间操作提供了更为灵活且方便的使用体验。 …

chatgpt赋能Python-python_plt_坐标轴

Python plt 坐标轴详解 介绍 在数据可视化领域中,matplotlib.pyplot是一款十分流行的python库。它支持绘制各种类型的图表,例如散点图、折线图、柱状图、饼图等。在绘制各种图表时,一个重要的因素就是如何调整和修改坐标轴以展示数据。本文…

chatgpt赋能Python-python_put

Python PUT:了解PUT请求 介绍 在RESTful API中,PUT请求用于更新资源,它是一种向服务器提交指定资源的请求方法。Python是一种流行的编程语言,其标准库中包含了支持基本HTTP协议的模块。Python的requests库是使用最广泛的HTTP库之…

小航编程题库机器人等级考试理论一级(2023年03月) (含题库教师学生账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统(含题库答题软件账号)_程序猿下山的博客-CSDN博客 单选题2.0分 删除编辑 答案:B 第1题关于使用动滑轮说法正确的是?( ) A、是否省力与动滑轮的颜色…

Java --- 期末复习卷

一、单选题 1.所有Java应用程序主类必须有一个名叫( )的方法。[ ] A.method B.main() C.java() D.hello 2.编写并保存了一个Java程序文件之后,( )它。[ …

NTLM认证协议

NTLM(Windows NT LAN Manager)是一种用于身份验证和安全通信的协议。它最初由微软开发,用于早期版本的Windows操作系统。NTLM协议在Windows网络环境中广泛使用,特别是在企业网络中。 NTLM身份验证步骤 NTLM验证是一种Challenge/R…

Java-API简析_java.lang.Class类(基于JDK1.8)(浅析源码)

【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://blog.csdn.net/m0_69908381/article/details/130838927 出自【进步*于辰的博客】 其实我的【Java-API】专栏内的博文对大家来说意义是不大的。…

【连续介质力学】涉及积分的定理

涉及积分的定理 分部积分 分部积分: ∫ a b u ( x ) v ′ ( x ) d x u ( x ) v ( x ) ∣ a b − ∫ a b v ( x ) u ′ ( x ) d x \int_a^bu(x)v(x)dxu(x)v(x)|_a^b-\int_a^bv(x)u(x)dx ∫ab​u(x)v′(x)dxu(x)v(x)∣ab​−∫ab​v(x)u′(x)dx 其中,…