【MySQL】深入解析索引实现原理

文章目录

    • 1、索引介绍
    • 2、索引分类
      • 2.1、数据结构
        • Hash
        • B + Tree
      • 2.2、存储方式
        • 聚簇索引
        • 非聚簇索引
      • 2.3、功能特性
        • 主键索引
        • 唯一索引
        • 普通索引
      • 2.4、字段数量
        • 单列索引
        • 多列索引
    • 3、最佳实践
      • 3.1、索引覆盖
      • 3.2、回表操作
      • 3.3、最左匹配原则
      • 3.4、索引下推

1、索引介绍

对于MySQL数据库来说,有个非常重要的概念就是索引,索引的用途是:

加速我们对MySQL数据库的查询操作性能,减少磁盘IO操作。

注意这里说的是查询,而不是新增、修改、删除。索引不仅对新增、修改等操作没有性能提升,并且还会降低这类DML(非查询SQL)操作的性能,原因很简单,因为DML操作还需要我们对索引结构不断进行维护…所以索引并不是越多越好,还是有维护的成本的,所以很多情况是可以考虑不创建索引的,例如:

  • 表数据量少
  • 字段重复数据多
  • 频繁进行DML操作的表

如果把MySQL比喻成一本书籍,那么索引就如同这本书籍的目录,我们通过目录就能大概确定我们想要页码的范围,这样就大大缩短了我们查找的时间,索引就类似这个工作方式,通过B+Tree就能够知道所查询行记录所在页,大大缩短了查询的范围,减少了对磁盘IO次数,提高查询性能。例如:我们为 t_user 表的 age 字段建立了索引,此时如果执行如下SQL,就会通过索引查询,性能非常快:
在这里插入图片描述

2、索引分类

无论是网上文章还是书中,经常会提到一大堆的索引概念,例如:主键索引、聚簇索引、二级索引、辅助索引、唯一索引…大家看到这些繁琐的名词就会觉得头晕,其实他们之间的很多概念都是重复的,例如我们常说的主键索引其实就是聚簇索引,接下来我们来具体看看不同维度下索引的分类有哪些。

2.1、数据结构

Hash

在Buffer Pool缓冲中有个部分就叫做:自适应哈希索引,这个索引采用的就是Hash的数据结构,也就是KV存储。频繁访问使用的索引页在一定场景下会被InnoDB自动转换成自适应Hash索引,自适应哈希索引采用的就是Hash的数据结构,这个转换不需要人为手动操作,Hash数据结构的索引时间复杂度为O(1),性能相比于后续提到的B+Tree结构要更快,不过Hash数据结构索引存储数据是无序的,并且不支持范围查询,除了自适应哈希索引,我们也可以为表中的字段手动创建Hash索引

B + Tree

这是InnoDB存储引擎默认的索引数据结构,听名字就知道该数据结构是根据索引字段构造出一个树状结构。树的顶部就是根节点,树干部分我们称之为非叶子节点,最下方的部分就是叶子节点,B+Tree的每个节点本质都是一个页(16KB)。B+Tree的树状结构会按照索引字段值就行排序,也就是有序的,最下方叶子节点数据通过双向链表进行连接,方便相邻索引页横向检索查询。对于B+Tree数据结构,一般来说树层高3~4层,因为即使在数据量很大的情况,查询一个数据的磁盘 I/O 依然维持在 3-4次。

2.2、存储方式

聚簇索引

聚簇索引这个概念听着很唬人,其实我换个称呼你就知道它的真面目了,其实聚簇索引就是主键索引聚簇索引索引数据表数据在磁盘中的位置是一起的,也就是说可以通过聚集聚集索引字段值直接找到对应整行表记录。一张表中除了主键索引属于聚簇索引,其他所有的索引都属于非聚簇索引(后面会提到),聚簇索引还有其他称呼:

  • 聚簇索引
  • 聚集索引
  • 主键索引

接下来看看数据也中聚簇索引 B+Tree样貌(下图来自于小林coding),B+Tree中每个节点都是,每个都会对应一个页号,假如我们条件查询想要查主键索引字段值为1的数据(聚簇索引就是主键索引),就会从根节点(页38)开始,不断向下遍历,直至通过B+Tree找到叶子节点(页10),从而找到该页中记录的索引字段值为1的data,在定位记录所在哪一个页时,也是通过二分法快速定位到包含该记录的页。定位到该页后,页中记录会被页目录进行分组,在该页内通过页目录进行二分法快速定位记录所在的分组(槽号),最后在分组内进行遍历查找行记录。

这里需要注意:聚簇索引叶子节点的行记录是主键索引对应的整行记录(包含所有的字段值),其中最大、最小记录可以理解为数据页中行记录的边界。图中绿色部分为聚簇(主键)索引字段值,叶子节点的蓝色部分data为聚簇(主键)索引字段值对应的整行记录。
在这里插入图片描述

非聚簇索引

什么是非聚簇索引呢?只需要记住除了主键索引(属于聚簇索引),其他类型的索引都属于非聚簇索引非聚簇索引索引数据表数据在磁盘中的位置不是一起的(跟聚簇索引相反),用物理地址的方式维护两者的联系,非聚簇索引还有其他称呼:

  • 非聚簇索引
  • 非聚集索引
  • 辅助索引
  • 二级索引

接下来看看数据也中非聚簇索引 B+Tree样貌(下图来自于小林coding),跟上面提到的聚簇索引 B+Tree最大的区别就是叶子节点的行记录不再是索引对应的一整行内容,而是索引字段对应行记录的主键字段值

注意:图中绿色部分为非聚簇索引字段值,叶子节点的蓝色部分为非聚簇索引字段值对应行记录的主键id。

在这里插入图片描述

2.3、功能特性

主键索引

主键索引(PRIMARY KEY)是非空且唯一的,也就是说不允许重复,更不允许为空。
在这里插入图片描述

对于InnoDB存储引擎来说,任何一张表都会有主键索引,即使在表中时没有指定那个字段为主键索引,InnoDB也必须保证必须要有一个主键索引,当没有主键索引时它会按照以下规则选择:

如果没有指定主键索引,那就查找是否有非空唯一索引,认作主键索引
如果没有非空唯一索引,那 InnoDB 将自动生成一个隐式自增 id 列作为主键索引(row_id)

唯一索引

唯一索引(UNIQUE KEY)是不允许重复的,主键索引和唯一索引的区别在于不允许有空值
在这里插入图片描述

普通索引

普通索引(KEY)就是建立在普通字段上的索引,既不要求字段数据唯一,也不要求非空
在这里插入图片描述

2.4、字段数量

单列索引

单列索引顾名思义,就是通过一个列(字段)创建的索引:
在这里插入图片描述

多列索引

多列索引又叫联合索引,多个字段(字段数量 ≥ 2)联合组成的索引,实际开发过程中建议尽可能使用联合索引来代替单列索引,并且还要符合特定规则情况下才能保证索引是有效的,这个规则就是最左匹配原则,后续会提到:
在这里插入图片描述

3、最佳实践

3.1、索引覆盖

索引覆盖是比较理想的索引使用方式,具体解释就是:本次SQL查询所需要的字段数据都可以在当前索引的B+Tree叶子节点上找到,举个例子:加入有一张t_user表,表中有四个字段:id、name、age、weight,此时根据name、age字段建立了联合索引,联合索引本身就是非聚簇索引,也就是叶子节点中行记录不会包含主键id对应的整行记录,所以该联合索引构成的 B+Tree 叶子节点中行记录就大体包含了:name、age字段值,行记录对应的主键id。

此时如果查询SQL为下方语句,通过EXPLAIN查看本次查询SQL的执行计划可以看到Using Index,所需数据只需在当前索引即可全部获得,不须要再到表中获取其他字段数据,就说明本次的查询操作进行了索引覆盖
在这里插入图片描述

但是下方这个SQL的查询操作就无法采用索引覆盖,因为weight字段值在叶子节点中不存在:
在这里插入图片描述

所以当非聚簇索引的B+Tree中字段值无法满足本次查询请求,就需要去聚簇索引的B+Tree中进行进一步查找,因为聚簇索引的叶子节点行记录是整行的,这步操作有个很官方的称呼,叫做回表,所以说到这里大家也该知道为啥不建议使用select *,其中一个原因就是这类SQL绝大多数情况下都需要进行回表操作,接下来画图解释一下什么是回表操作。

3.2、回表操作

上面大致介绍过了,回表简单来说就是查询字段信息无法在非聚簇索引B+Tree的行记录中完全拿到,需要在查询一次聚簇索引B+Tree,拿到缺失的字段信息,所以只能先从非聚簇索引找到查询目标行所对应的主键id,然后根据主键id回到聚簇索引中查询整行记录,拿到想要的信息,如下图:
在这里插入图片描述

3.3、最左匹配原则

针对与多列索引(非聚簇索引)有个很重要的概念叫做最左匹配原则。简单来说就是我们的查询SQL如果想要命中联合索引,那么查询条件就要有一定的规则顺序,例如创建了一个 (a, b, c) 联合索引:

# 符合(由于优化器存在,a顺序不重要)
where a = 1where a = 1 and b = 2where a = 1 and b = 2 and c = 3# 不符合,索引失效
where b = 2where c = 3where b = 2 and c = 3

之所以需要匹配,原因就是B+Tree索引结构是有序的,根据a,b,c建立联合索引,InnoDB会从a字段开始排序,然后再是b,最后是c;所以单单通过b,c自然就无法进行排序查找。

MySQL的最左前缀原则,在匹配到范围查询时会停止匹配,比如>、<、between、like这类范围条件,并不会继续使用联合索引,例如:where a = 1 and b > 2 and c = 3,则会在每个节点依次命中ab,无法命中c。对于联合索引的建立有个技巧,就是把查询条件使用频次多的字段放到前面,这样尽可能的能够踩中最左匹配原则

3.4、索引下推

索引下推是InnoDB5.6版本诞生的优化特性,它出现就是为了减少回表次数,提高查询效率。上面讲最左匹配原则是提到过遇到范围查询条件时会停止规则匹配,例如:>、<、between、like,那么当我们对a,b建立联合索引,此时查询条件为:

select a,b,c fromwhere a > 10 and b = 100

此时只有 a 踩中了索引,假设此时查询a,b,c字段信息是需要回表,那么它并不会直接开始回表操作,它在继续回表前,先将b字段的判断条件进行一次筛选,如果不符合本次查询到行记录b字段值,那就没必要在进行回表了,这就是索引下推ICP,减少了回表次数,提高查询性能。

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

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

相关文章

笔试题:小红的循环小数 数论 欧拉 快速幂 小费马定理

小红的循环小数 众所周知&#xff0c;所有的无限循环小数都可以写成分数的形式 小红想让你判断循环节长度为k的无限循环小数的分母是否可能是p。你能帮帮她吗&#xff1f; 共有q次询问。 输入描述 第一行输入一个正整数 q q q&#xff0c;代表询问次数。 接下来的 q q q行&…

Tensorflow笔记(二):常用函数2、激活函数、优化器等、神经网络模型实现(商品销量预测)

import tensorflow as tf import numpy as np from tqdm import tqdm# ----------------------------- tensor常用函数2 ----------------------------------- a tf.constant([1, 2, 3, 1, 2]) b tf.constant([0, 1, 3, 4, 5]) c tf.where(tf.greater(a, b), a, b) # 若a&g…

计算机毕业设计-springboot+vue前后端分离电竞社交平台管理系统部分成果分享

4.5系统结构设计 本系统使用的角色主要有系统管理员、顾客、接单员&#xff0c;本系统为后台管理系统&#xff0c;游客用户可以经过账号注册&#xff0c;管理员审核通过后&#xff0c;用账号密码登录系统&#xff0c;查看后台首页&#xff0c;模块管理&#xff08;顾客信息&am…

mysql重构

力扣题目链接 列转行 SELECT product_id, store1 store, store1 price FROM products WHERE store1 IS NOT NULL UNION SELECT product_id, store2 store, store2 price FROM products WHERE store2 IS NOT NULL UNION SELECT product_id, store3 store, store3 price FROM p…

全栈的自我修养 ———— js中的复制api

通常用于可以禁止用户复制或者在复制的内容后面添加版权信息等 一、代码二、展示1、访问粘贴板的内容2、替换复制内容3、在复制内容的后面添加版权信息4、监听粘贴事件 一、代码 <body><div class"demo">不可以被复制</div><div class"de…

如何从任何文档生成指令数据集以进行LLM微调

使用轻量级库经济地生成高质量的合成数据集 大型语言模型 &#xff08;LLMs&#xff09; 是功能强大的通用工具&#xff0c;但它们通常缺乏特定于领域的知识&#xff0c;这些知识通常存储在企业存储库中。 使用您自己的数据微调自定义LLM可以弥合这一差距&#xff0c;而数据准…

【Shiro反序列化漏洞】Shiro-550反序列化漏洞复现

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

了解下索引的几棵树?

二叉树 二叉搜索树最好的情况性能是O(logn)&#xff0c;最坏情况是O(n) 红黑树 它的时间复杂度是O(logn)&#xff0c;但是在数据量特别大的时候&#xff0c;树会特别高&#xff0c;就会遍历很多层级&#xff0c;对性能影响较大 BTree B树是一种多叉路衡查找树&#xff0c;相对于…

解决NVM安装Node失败:淘宝NPM镜像HTTPS证书到期及源切换指南

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

如果利用AOP/Aspect来修改方法的入参

问题描述&#xff1a; 最近项目代码过三方测试&#xff08;国企项目&#xff09;&#xff0c;在一系列代码扫描审计检查下&#xff0c;代码发现一部分修改&#xff0c;例如请求参数发生了编码/加密&#xff0c;导致后台需要对请求的参数进行解码/解密&#xff0c;后端那么接口&…

访问者模式(Visitor Pattern)

访问者模式 说明 访问者模式&#xff08;Visitor Pattern&#xff09;属于行为型模式&#xff0c;表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 该模式是将数据结构与数据操作分离的设计模式&#xff0c;是…

Flutter 多语言、主题切换之GetX库

多语言、主题切换之GetX库 前言正文一、配置项目二、模拟UI三、语言配置① 常量键② 语言配置文件③ 配置 四、持久化五、切换语言① my_home.dart② home.dart③ mine_controller.dart④ language_setting_controller.dart⑤ language_setting.dart⑥ mine.dart 六、切换主题①…

基于SpringBoot的“家政服务管理平台”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“家政服务管理平台”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统首页界面图 用户注册界面图 服务信息界面…

WorldGPT、Pix2Pix-OnTheFly、StyleDyRF、ManiGaussian、Face SR

本文首发于公众号&#xff1a;机器感知 WorldGPT、Pix2Pix-OnTheFly、StyleDyRF、ManiGaussian、Face SR HandGCAT: Occlusion-Robust 3D Hand Mesh Reconstruction from Monocular Images We propose a robust and accurate method for reconstructing 3D hand mesh from m…

ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。

发生的错误信息&#xff1a; File "C:\Users\malongqiang\.conda\envs\ObjectDetection\lib\ssl.py", line 1309, in do_handshakeself._sslobj.do_handshake() ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。 分析原因&#xff1a; …

接口的回调

接口是引用型变量 接口回调技术&#xff1a;把实现该接口的类的实例引用赋给接口变 量&#xff08;存放对象的引用&#xff09;→接口变量可调用被类重写的接口方法。 ★注意★&#xff1a;接口com无法调用类中非接口方法

SQL语句在MySQL中的执行过程

有一条SQL语句&#xff0c;给到MySQL,是怎么被执行的 基本架构 连接器&#xff1a;进行身份认证&#xff0c;确定操作权限 查询缓存&#xff1a; 执行查询语句时&#xff0c;先查询缓存&#xff08;不太实用&#xff0c;MySQL 8.0 版本后删了&#xff09; 分析器&#xff1a…

格子表单GRID-FORM | 必填项检验 BUG 修复实录

格子表单/GRID-FORM已在Github 开源&#xff0c;如能帮到您麻烦给个星&#x1f91d; GRID-FORM 系列文章 基于 VUE3 可视化低代码表单设计器嵌套表单与自定义脚本交互文档网站搭建&#xff08;VitePress&#xff09;与部署&#xff08;Github Pages&#xff09;必填项检验 BUG…

搭建谷歌Gemini

前言 Gemini是Google AI于2023年发布的大型语言模型&#xff0c;拥有强大的文本生成、理解和转换能力。它基于Transformer模型架构&#xff0c;并使用了大量文本和代码数据进行训练。Gemini可以执行多种任务&#xff0c;包括&#xff1a; 生成文本&#xff1a;可以生成各种类…

一张图让你学会Python

有编程基础的人一看就可以了解 Python 的用法了。真正的 30 分钟上手。 国外一高手画的&#xff0c;现把它翻译成中文&#xff0c;入门超简单 python入门神图!(看不清可以“另存为”查看)