【MySQL索引学习】MySQL索引详细学习

news2024/9/25 17:19:11

一、什么是索引

索引是一种用于快速查询和检索数据的数据结构。 可以将其类比于书的目录。

索引底层的数据结构存在很多种类型,常见的索引结构有: B 树, B+树 和 Hash、红黑树。在 MySQL 中,无论是 Innodb 还是 MyIsam,都使用了 B+树作为索引结构。

二、索引的优缺点

优点:

  • 使用索引可以大大加快 数据的检索速度(大大减少检索的数据量), 这也是创建索引的最主要的原因
  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性

缺点:

  • 创建索引和维护索引会消耗时间。当对表中数据进行增、删、改的时候,如果数据有索引,那么索引也需要动态修改,会降低SQL的执行效率。
  • 索引需要使用物理文件存储,会消耗一定的物理空间。

(我们思考这样一个问题:使用索引一定能提高查询性能吗?
大多数情况下,索引查询都是比全表扫描要快的。但是如果数据库的数据量不大,那么使用索引也不一定能够带来很大提升。)

三、Mysql为什么使用B+树做索引?

Mysql默认使用的是Innodb引擎,当然MySQL也支持其他的存储引擎如MyISAM等,无论是Innodb还是MyISAM都是使用了B+树作为索引结构,下面我们来分析下索引底层数据结构选型,为什么使用B+树做索引?

(一)为什么不用Hash表?

哈希表存储的元素是键值对,通过键(key)即可快速取出对应的值(value),因此哈希表可以快速检索数据(接近 O(1))。

既然哈希表这么快,为什么 MySQL 没有使用其作为索引的数据结构呢?
主要是因为 Hash 索引不支持顺序和范围查询。假如我们要对表中的数据进行排序或者进行范围查询,那 Hash 索引可就不行了。并且,每次 IO 只能取一个

(试想一种情况:

SELECT * FROM tb1 WHERE id < 1000;

在这种范围查询中,优势非常大,直接遍历比 1000 小的叶子节点就够了。而 Hash 索引是根据 hash 算法来定位的,难不成还要把 1 - 999 的数据,每个都进行一次 hash 计算来定位吗?这就是 Hash 最大的缺点了。

(二)为什么不使用二叉查找树

二叉查找树(Binary Search Tree)是一种基于二叉树的数据结构,它具有以下特点:

  • 左子树所有节点的值均小于根节点的值。
  • 右子树所有节点的值均大于根节点的值。
  • 左右子树也分别为二叉查找树。

当二叉查找树是平衡的时候,也就是树的每个节点的左右子树深度相差不超过 1 的时候,查询的时间复杂度为 O(log2(N)),具有比较高的效率。然而,当二叉查找树不平衡时,例如在最坏情况下(有序插入节点),树会退化成线性链表(也被称为斜树),导致查询效率急剧下降,时间复杂退化为 O(N)。
在这里插入图片描述
也就是说,二叉查找树的性能非常依赖于它的平衡程度,这就导致其不适合作为 MySQL 底层索引的数据结构。

(三)为什么不使用AVL(平衡二叉树) 树

平衡二叉树(AVL 树)是计算机科学中最早被发明的自平衡二叉查找树AVL 树的特点是保证任何节点的左右子树高度之差不超过 1,因此也被称为高度平衡二叉树,它的查找、插入和删除在平均和最坏情况下的时间复杂度都是 O(logn)
在这里插入图片描述
那为什么不使用AVL树作为索引呢?原因有如下两点:

  • 1、AVL树是高度平衡的二叉树,需要频繁地进行旋转操作来保持平衡,因此会有较大的计算开销进而降低了查询性能
  • 2、在使用 AVL 树时,每个树节点仅存储一个数据,而每次进行磁盘 IO 时只能读取一个节点的数据,磁盘 IO 是一项耗时的操作,而我们在设计数据库时需要最大限度地减少磁盘 IO 操作的次数。

(四)为什么不用红黑树

红黑树是一种自平衡二叉查找树,通过在插入和删除节点时进行颜色变换和旋转操作,使得树始终保持平衡状态。和 AVL 树不同的是,红黑树并不追求严格的平衡,而是大致的平衡。

红黑树的应用还是比较广泛的,例如 JDK1.8 的 HashMap 底层用到了红黑树。对于数据在内存中的这种情况来说,红黑树的表现是非常优异的。

但为什么不会用红黑树来作为索引呢?
原因:
在使用红黑树时,每个树节点仅存储一个数据,而每次进行磁盘 IO 时只能读取一个节点的数据,磁盘 IO 是一项耗时的操作,而我们在设计数据库时需要最大限度地减少磁盘 IO 操作的次数。

(五)B树 & B+树

B 树也称 B-树,全称为 多路平衡查找树 。B+树是B树的一种变化。
目前大部分数据库系统及文件系统都采用 B-Tree 或其变种 B+Tree 作为索引结构。

B树 和 B+树有何异同?Mysql的InnoDB 和 MyISAM 引擎为何都选用B+树作为索引结构?(***)

概述:

  • 1、B+树的磁盘IO次数更少。B+树非叶子节点只存储key,可以存放更多的键值。
  • 2、B+树叶子节点间是通过双向链表连接,便于顺序查找。
  • 3、B+树支持顺序查找、范围查找、分组查找更容易
  • 4、B+树查找效率稳定。任何查找都是从根节点到叶子节点的过程。

详细分析:

  • B 树的所有节点既存放键(key) 也存放数据(data),而 B+树只有叶子节点存放 key 和 data,其他内节点只存放 key。(这样。如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快。)
  • B 树的叶子节点都是独立的;B+树中各个叶子节点之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的。
  • B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。而B树因为数据分散在各个节点,要实现这一点是很不容易的。
  • B 树的检索的过程相当于对范围内的每个节点的关键字做二分查找,可能还没有到达叶子节点,检索就结束了。而 B+树的检索效率就很稳定了,任何查找都是从根节点到叶子节点的过程,叶子节点的顺序检索很明显

综上,B+树与B树相比,其查找过程IO次数更少,且具备更稳定的查询效率和范围查询这些优势。

(附加:
在MySQL中,InnoDB引擎和MyISAM引擎都是使用B+树作为索引结构,但两者的实现方式不太一样:

  • 在InnoDB引擎中主键索引使用的是聚簇索引非主键索引(二级索引)使用的是非聚簇索引
  • MyISAM引擎中无论是主键索引还是非主键索引使用的都是非聚簇索引

四、聚簇索引和非聚簇索引

(一)聚簇索引

聚簇索引索引和数据一起存放的索引。即聚簇索引的每个非叶子节点存储的是索引,而每个叶子节点存储的是索引和索引对应的数据

主键索引其就是聚簇索引

优点:

  • 1、查询速度非常块。因为聚簇索引(即主键索引)其是基于B+树这种数据结构,其非叶子节点存储的是主键索引,而非叶子节点存储的是主键索引及其对应的数据。只要定位到了节点就相当于找到了这条数据,其相比与非聚簇索引少了回表或是查找数据文件这些操作。
  • 2、对于排序查找和范围查找更加友好。聚簇索引是有序的,其叶子节点是有序的,对于主键的排序查找和范围查找的速度非常快。

缺点:

  • 1、依赖于有序的数据。因为B+树是多路平衡树,如果索引的数据不是有序的,那么就需要在插入的时候进行排序,这样对于插入和查找的效率就肯定会慢。
  • 2、更新代价大。对于聚簇索引,在修改其索引时候,因为其叶子节点不仅存储了索引同时也存储了数据,这样其修改代价肯定是较大的。(对于主键索引来说,主键一般是不可被修改的)。

聚簇索引查找流程示意图如下:
在这里插入图片描述

(二)非聚簇索引

非聚簇索引索引和数据分开存放的。即非聚簇索引的每个非叶子节点存放的是也是索引,但叶子节点存放的却是数据的指针或是主键。(当查询到索引对应的指针或是主键后,还需要根据指针或是主键再到数据文件或是表中进行查询)

非主键索引(二级索引即辅助索引)就是非聚簇索引

优点:

  • 更新代价比聚簇索引要小 。非聚簇索引的更新代价就没有聚簇索引那么大了,非聚簇索引的叶子节点是不存放数据的

缺点:

  • 1、依赖于数据的有序性。和聚簇索引一样非聚簇索引也依赖于数据的有序性。
  • 2、可能会二次查询或回表。这应该是非聚簇索引最大的缺点了。 当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。

在这里插入图片描述

非聚簇索引查找流程如下:
在这里插入图片描述

五、主键索引 和 二级索引

(一)主键索引

数据表中主键使用的就是主键索引。

一张数据表有只能有一个主键,并且主键不能为 null,不能重复。

在 MySQL 的 InnoDB 的表中,当没有显示的指定表的主键时,InnoDB 会自动先检查表中是否有唯一索引且不允许存在 null 值的字段,如果有,则选择该字段为默认的主键,否则 InnoDB 将会自动创建一个 6Byte 的自增主键。
在这里插入图片描述
主键索引就属于聚簇索引,其叶子节点data存放的是主键及主键对于的完整的数据。

(二)二级索引

二级索引(Secondary Index)又称为辅助索引,是因为二级索引的叶子节点存储的数据是主键。也就是说,通过二级索引,可以定位主键的位置。(然后通过回表进而查询到索引对应的数据)

唯一索引普通索引前缀索引等索引属于二级索引。
在这里插入图片描述
其中:

  • 1、唯一索引(Unique Key):唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为 NULL(主键索引是不允许数据为NULL),一张表允许创建多个唯一索引。 建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
  • 2、普通索引(Index):普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和 NULL。
  • 3、前缀索引(Prefix):前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小, 因为只取前几个字符。

六、覆盖索引

我们前面说了二级索引,非聚簇索引的叶子节点存储的是主键的值,通过索引可以定位主键的位置。(然后通过回表进而查询到索引对应的数据)。那非聚簇索引一定回表查询吗(覆盖索引)?

非聚簇索引不一定回表查询。
试想一种情况,用户准备使用 SQL 查询用户名,而用户名字段正好建立了索引。

SELECT name FROM table WHERE name='AAA';

那么这个索引的 key 本身就是 name,查到对应的 name 直接返回就行了,无需回表查询。

覆盖索引

如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为 覆盖索引(Covering Index)

覆盖索引即需要查询的字段正好是索引的字段,那么直接根据该索引,就可以查到数据了,而无需回表查询。

(注意:
覆盖索引是索引优化的一种常用手段(重点)。
由于覆盖索引的索引即为所要查询的字段的数据,无需进行回表查询,减少了树的搜索次数,显著提高了查询性能,所以使用覆盖索引是索引优化的一种常用手段

七、联合索引

联合索引,即使用表中的多个字段创建索引,就是 联合索引

以 score 和 name 两个字段建立联合索引:

ALTER TABLE `Student_Grade` ADD INDEX id_score_name(score, name);

最左前缀匹配原则

最左前缀匹配原则指的是,在使用联合索引时,MySQL 会根据联合索引中的字段顺序,从左到右依次到查询条件中去匹配,如果查询条件中存在与联合索引中最左侧字段相匹配的字段,则就会使用该字段过滤一批数据,直至联合索引中全部字段匹配完成,

如果最左边的字段不能完全匹配,那么会依次向右移动,对下一个字段进行匹配,直到所有的字段都被匹配或者无法找到匹配项为止。

所以,我们在使用联合索引时,可以将区分度高的字段放在最左边,这也可以过滤更多数据。

八、索引下推

索引下推:是MySQL5.6版本的新特性,用于优化数据查询。当存储引擎通过索引检索到数据并返回给MySQL服务器时,服务器会判断数据是否符合条件。在使用索引条件下推优化时,如果存在某些被索引的列的判断条件,MySQL服务器将这一部分判断条件传递给存储引擎,由存储引擎通过判断索引是否符合MySQL服务器传递的条件,只有当索引符合条件时才会将数据检索出来返回给MySQL服务器。

这种优化可以减少存储引擎查询基础表的次数,也可以减少MySQL服务器从存储引擎接收数据的次数,从而提高了查询效率。简单来说,索引下推就是将原本由上层(服务层)负责的部分任务交给了下层(引擎层)去处理

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

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

相关文章

如何在 Nginx 中隐藏版本号

文章目录 修改nginx.conf文件修改fastcgi.conf文件参考文档 修改nginx.conf文件 打开 Nginx 配置文件&#xff0c;一般在 /etc/nginx/nginx.conf 或 /usr/local/nginx/conf/nginx.conf。在 http 块中添加以下内容&#xff1a;server_tokens off;修改fastcgi.conf文件 编辑php…

kafka 消费者的消费策略以及再平衡1

一kafka 再平衡 1.1 kafka的再平衡 Kafka的再平衡是consumer所消费的topic发生变化时&#xff0c;topic上的分区再次分配的情况。 默认策略是 Range CooperativeSticky 。 Kafka 可以同时使用 多个分区分配策略。 1.2 kafka触发再平衡的情况 1.consumer group中的新增或删…

Windows系统webp图片预览插件

由于工作中经常需要对组图查看和管理&#xff0c;而Windows 7系统不支持在文件夹下直接预览webp图片。经过查找&#xff0c;发现 WebP Codec for Windows 扩展插件不错&#xff0c;完美地解决webp图片预览问题。 目录 1、webp文件浏览插件 2、下载插件并安装 3、浏览webp图片…

vue项目部署,出现两个ip的原因

我宁愿靠自己的力量打开我的前途,而不愿求有力者的垂青。——雨果 tags: 篇首语&#xff1a;本文由小常识网(cha138.com)小编为大家整理&#xff0c;主要介绍了vue项目部署&#xff0c;出现两个ip的原因相关的知识&#xff0c;希望对你有一定的参考价值。 参考技术A 在部署v…

Linux网络编程|TCP编程

一.网络基础 1.1网络发展史 Internet&#xff0d;“冷战”的产物 1957年10月和11月&#xff0c;前苏联先后有两颗“Sputnik”卫星上天 1958年美国总统艾森豪威尔向美国国会提出建立DARPA (Defense Advanced Research Project Agency)&#xff0c;即国防部高级研究计划署&#…

机器学习练习-决策树

机器学习练习-决策树 代码更新地址&#xff1a;https://github.com/fengdu78/WZU-machine-learning-course 代码修改并注释&#xff1a;黄海广&#xff0c;haiguang2000wzu.edu.cn 1&#xff0e;分类决策树模型是表示基于特征对实例进行分类的树形结构。决策树可以转换成一个if…

Jsoup | Document | HTML解析器

Jsoup 一、获取 <p>标签下的所有图片 一、获取 <p>标签下的所有图片 <p> <img style"max-width: 100%;" src"http://image.svipjf.cn/1678271098160-480_01.jpg"/><img src"http://image.svipjf.cn/1678271097994-480_02…

FPGA project: uart_rs485

没有设计rs485的顶层&#xff0c;因为我的另一块板子没有TTL信号转差分信号的芯片&#xff1a;MAX3485CSA module ctrl(input wire sys_clk ,input wire sys_rst_n ,input wire key_w ,input …

如何使用 RunwayML 进行创意 AI 创作

标题&#xff1a;如何使用 RunwayML 进行创意 AI 创作 介绍 RunwayML 是一个基于浏览器的人工智能创作工具&#xff0c;可让用户使用各种 AI 功能来生成图像、视频、音乐、文字和其他创意内容。RunwayML 的功能包括&#xff1a; * 图像生成&#xff1a;使用生成式对抗网络 (…

零基础也能快速上手活动海报设计

在现代社会中&#xff0c;活动海报设计已经成为推广活动、宣传信息的重要手段之一。然而&#xff0c;对于大部分人来说&#xff0c;设计一张漂亮的海报可能会觉得困难重重。不过&#xff0c;不用担心&#xff01;现在有了乔拓云&#xff0c;零基础的你也能轻松上手活动海报设计…

GraphBase基础原理

一、GraphBase简介 互联网时代&#xff0c;随着网络技术的发展&#xff0c;企业积累的数据越来越多。伴随着数据集的不断增加&#xff0c;传统的关系型数据库查询性能会随之变差&#xff0c;特别是针对一些特殊的业务场景&#xff0c;所以迫切的需要一种新的解决方案去应对这种…

[腾讯云 Cloud Studio 实战训练营] 云上编程的革命:我的 Cloud Studio 体验之旅

文章目录 1. 无缝的云端体验1.1 云端工作站的魅力1.2 真正的在线编程1.3 强大的协作能力1.4 多平台兼容性1.5 安全和数据备份1.6 持续更新和维护1.7 灵活的资源扩展 2. 功能强大的在线 IDE2.1 基础功能全覆盖2.2 高级功能支持2.3 多语言支持2.4 自定义工作流程2.5 版本控制和协…

单元格法近似求解多边形最大内接矩形问题【思路讲解+java实现】

文章目录 问题描述问题解决方案多边形网格化区分每个单元格是在多边形内部还是外部根据已标记单元格寻找最大内接矩形剪枝优化多角度旋转 案例测试代码实现说明 问题描述 给定一个多边形的点集&#xff0c;希望找出多边形内部面积最大的矩形。该问题可能出现在&#xff0c;从一…

Linux命令200例:cu是用于设置与终端设备通信的工具

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0…

Netsh命令修复DNS无法上网问题

关注【潇湘信安】、【Hack分享吧】公众号&#xff0c;一起学网络安全知识&#xff01; 0x01 问题描述 今早打开电脑后突然发现上不了网了&#xff0c;TIM可以正常登录&#xff0c;浏览器打不开网页&#xff0c;出现这样情况一般都是DNS的问题&#xff0c;用ipconfig /all命令查…

Kotlin文件遍历FileTreeWalk filter

Kotlin文件遍历FileTreeWalk filter import java.io.Filefun main(args: Array<String>) {val filePath "."val file File(filePath)val fileTree: FileTreeWalk file.walk()fileTree//.maxDepth(1) //遍历层级1&#xff0c;不检查子目录.filter {it.isFile…

【Java 基础篇】深入理解Java集合嵌套:构建和管理复杂数据结构的终极指南

当我们谈论集合嵌套时&#xff0c;我们指的是在一个集合中存储另一个集合&#xff0c;或者说集合中的元素本身也是集合。这是一个非常有用的概念&#xff0c;可以在处理复杂数据结构时提供更灵活的选项。在本文中&#xff0c;我们将深入探讨Java中集合嵌套的概念、用法以及一些…

Jenkins 编译 Maven 项目提示错误 version 17

在最近使用集成工具的时候&#xff0c;对项目进行编译提示下面的错误信息&#xff1a; maven-compiler-plugin:3.11.0:compile (default-compile) on project mq-service: Fatal error compiling: error: release version 17 not supported 问题和解决 上面提示的错误信息原…

Llama.cpp工具main使用手册

Llama.cpp提供的 main工具允许你以简单有效的方式使用各种 LLaMA 语言模型。 它专门设计用于与 llama.cpp 项目配合使用。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 Llama.cpp的工具 main提供简单的 C/C 实现&#xff0c;具有可选的 4 位量化支持&#xff0c;可实现…

C++之默认与自定义构造函数问题(二百一十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…