【MySQL数据库 | 第十七篇】索引以及索引结构介绍

news2025/2/11 9:13:05

目录

前言:

索引简介: 

索引结构:

          二叉树索引结构

        Tree(普通二叉树)

        B-Tree(多路平衡查找树)

        B+Tree

         哈希索引数据结构

总结:


前言:

在实际生活中,我们对SQL语句进行优化实际上有很大一部分都是对索引进行优化,因此对索引有一个较好的掌握度至关重要。而讲索引必定会引用到很多的数据结构,因此我们在这里向大家提供一个网站:数据结构可视化 (usfca.edu)。他会对我们输入的数据逐步生成我们想要演示的数据结构动图。方便各位对各种数据结构有更加深刻的了解。

索引简介: 

          索引是用于加速数据库中数据检索的一种有序的数据结构。在数据库中,数据存储在表中,表中的每一行称为记录,每一列称为字段。当我们需要检索、查询表中的某些数据时,如果表中数据量很大,那么就会变得非常耗时。这时,使用索引可以快速定位到符合条件的记录,从而提高查询效率。

          索引的本质是一个存储有序键值对的数据结构,其中键是表中某一列的值,而值是指向该值所在记录的指针。索引对于某一列的值建立了快速的查找路径,使得查询操作不再需要对整个表中的数据进行扫描,而是直接定位到符合条件的记录。

索引类型:

  • B树索引
  • B+树索引
  • hash索引

        当没有索引的时候,如果我们要对一个数据库进行条件查询操作,我们的数据库会对每一条数据都进行查询判断,直到找出来符合条件的数据

B树和B+树

B树和B+树都是一种基于磁盘存储的平衡树,被广泛应用于数据库索引结构中。它们的主要区别在于:

       1. B树中既存储数据又存储索引,而B+树只存储索引,数据存储在叶子节点上。

       2. B树的每个节点可以存储的关键字数目较小,一般不超过2个。而B+树的每个节点可以存储的关键字数目较多,一般可以存储几十个甚至几百个。

       3. B树中的非叶子节点和叶子节点的存储方式不同,而B+树的非叶子节点和叶子节点的存储方式相同。

       4. B树采用的是节点分裂和合并方式来维护平衡,而B+树采用的是节点分裂和叶子节点链表方式来维护平衡。

因为B+树节点只存储索引,数据存储在叶子节点上,因此在查询范围查找、顺序查找的情况下,B+树比B树更适合,因为B+树的叶子节点形成了一个链表,可以很快地查找到指定范围内的数据。而对于B树,需要遍历整个树结构才能找到想要的数据,这会导致非常高的时间成本。在数据库索引的应用中,B+树是更常用的一种索引结构。

案例:

       例如我们如果要查询年龄大于40岁的员工,此时我们没有建立索引,我们就会逐一遍历这些数据,直至数据完结。(并不是找到一条符合条件的之后就结束查询,而是会遍历完整个表,因为无法确定这条数据之后还是否会有符合条件的数据)。

我们把这种查询方式叫做全表查询。

无索引查询:

索引的优点:

  1. 提高数据的查询效率:索引可以加快数据库的查询效率。通过建立索引,可以对关键字进行快速的定位和访问,从而最大限度地减少了磁盘I/O的次数,降低查询数据的时间成本。

  2. 减少数据的重复存储:索引存储的是关键字的位置信息,可以避免在表中重复存储关键字,减少数据的存储空间,提高存储效率。

  3. 提高数据的完整性和准确性:索引可以对数据进行唯一性、完整性约束,防止数据重复或者无效数据的出现。

  4. 优化数据的排序和分组操作:索引可以优化数据的排序和分组操作,使这些操作更快捷和更有效率。

  5. 支持高并发查询操作:在高并发的情况下,索引可以提高数据库的查询效率,减少数据库的响应时间,从而提升了系统的性能。

索引的缺点:

  1. 增加了存储空间和维护成本:索引需要占用额外的存储空间,并且每次对数据进行更新、插入或删除等操作时都需要更新对应的索引,增加了维护成本。

  2. 索引可能不适用于所有查询:不是所有查询都能够使用索引。如果查询中包含了大量的计算、表达式、函数或者是使用了非索引列进行排序和分组,那么索引对于提高查询效率的作用就会较小。

  3. 索引可能造成资源竞争和锁的问题:当多个客户端同时访问同一个索引时,就可能会出现资源竞争和锁的问题,降低系统的并发性和性能。

  4. 索引可能会降低数据更新、插入和删除的效率:因为每次对数据进行更新、插入或删除等操作时都需要更新对应的索引,所以这些操作的效率可能会降低。

索引结构:

       索引结构随着底层的存储引擎不同而会有不同的数据结构。

     引擎对索引的支持情况:
 

     我们平时说的索引,如果没有特别指明,都是指B+树结构组织的索引。

二叉树索引结构

Tree(普通二叉树)

 在这里我们可以看到:如果二叉树是按照顺序结构插入,那么他就是一个链表,查询性能会大大降低。

而为了解决顺序结构的插入问题,我们引入了红黑树。

而为了解决二叉树在层级较深的时候,会有检索速度慢的问题。我们又想到了一个方法:

      既然检索速度慢是因为每个层级只能有两个节点,那我们能否开发出来一种树,而这种树每一个层级拥有多个节点,那么我们不就解决了数据结构多的情况下普通树太多引发的层级过多的问题。

B-Tree(多路平衡查找树)

B-Tree树的生成分裂问题一直都是一个难点,搞不清楚的同学可以去这个网站:B-Tree Visualization (usfca.edu),自己输入几组数据,它会自动生成从0开始形成树的动图来让各位同学对B-Tree的形成更有体会。

我们以一颗最大度数为5的b-tree为例(每个接待你最多存储4个key,五个指针)

树的度数就是指一个节点的子节点个数:

 翻译一下最上级的指针指向:

  • 小于20的指向一个节点

  • 20到30之间的指向一个节点

  • 30到62之间的指向一个节点

  • 62到89之间的指向一个节点

  • 大于89的指向一个节点

这也就是为什么指针的数量总是比数据的数量多一个

B+Tree

B+树节点只存储索引,数据存储在叶子节点上,因此在查询范围查找、顺序查找的情况下,B+树比B树更适合,因为B+树的叶子节点形成了一个链表,可以很快地查找到指定范围内的数据。

 B+树的特点:

  • 所有的数据都会出现在叶子节点。
  • 叶子节点形成一个单向链表。

但需要注意的是MySQL索引中并不会直接使用这种原版的B+树,而是做了以下改进:

  •      向叶子节点中的各个节点再次添加一个指针,以此来指向相邻的节点,这种做法优化了在查询数据的时候的遍历问题,优化了时间复杂度。

 哈希索引数据结构

       哈希索引是一种常见的索引结构,它使用哈希函数将关键字映射到哈希表中的位置,从而实现快速的查找操作。在哈希表中,每个关键字都被分配一个唯一的哈希值,这个哈希值通常是一个整数,它表示该关键字在哈希表中的位置。

       当需要查找一个关键字时,哈希函数可以快速计算出它在哈希表中的位置,并且只需要访问一个位置,就可以找到对应的数据。因此,哈希索引具有非常高效的查找性能,速度快且稳定。

       但是,哈希索引也有一些局限性。由于哈希函数是不可逆的,无法直接从哈希值中恢复原始数据,所以哈希索引不支持范围查找和排序操作。并且,当多个关键字被映射到同一个哈希值时,哈希表必须使用冲突解决策略来处理这些冲突。常见的冲突解决方法包括链式哈希和开放地址哈希等。

链式哈希(Chaining Hash)开放地址哈希(Open Addressing Hash)都是常用的哈希表实现方式。

       1.链式哈希将哈希冲突的元素放入同一个链表中,每个链表节点包含了关键字和对应的值,链表头节点位于哈希表中的对应槽位中。插入操作只需要先对元素进行哈希计算找到相应的槽位,然后再在对应槽位的链表中进行元素的插入,查找操作只需要先对元素进行哈希计算找到相应的槽位,然后再在对应槽位的链表中进行线性查找即可。

       2.开放地址哈希则是在哈希表中找到一个可用的槽位作为元素存放的位置。当遇到冲突时,需要根据哈希表中不同的探查序列方法(例如线性探查、二次探查或双重哈希等),搜索哈希表中下一个可用的槽位,直到找到可用的槽位。这种方法使得哈希表中不需要链表等额外空间来存储冲突的元素,从而节约了空间。

 哈希表索引数据结构(链式哈希解决的哈希冲突)

 哈希索引特点:

  1. 快速查找:哈希索引通过对关键字进行哈希函数运算,将其映射到哈希表中的一个特定位置,从而可以快速的查找到对应的数据。对于大量数据的查询,哈希索引比其他类型的索引更快。

  2. 不支持排序和模糊匹配:与其他类型的索引相比,哈希索引重点在于等值查找,不支持通过关键字进行排序或者模糊匹配。因此,在需要排序或者模糊查询的情况下,哈希索引比较无效。

  3. 不支持范围查询哈希索引是用哈希函数将关键字转化为固定的位置索引,因此不支持范围查询。

  4. 内存占用较小:哈希索引中不需要存储关键字的排序值,只需要存储关键字哈希值及其对应的指针向量。因此,哈希索引的内存占用较小。

  5. 高并发时性能较差:当有大量并发查询时,因为哈希索引使用哈希函数将关键字映射到表中一个位置,不同数据可能被映射到同一个位置,从而导致哈希冲突,因此当前查询可能需要等待前一个查询完成,导致效率降低。

哈希检索通常只需要一次检索(不出现哈希碰撞)哈希索引的效率通常要比B+树索引的查询效率高

在MySQL中,目前只有Memory引擎支持hash索引。

总结:

        索引的数据结构形式多种多样,我们只有学好底层的数据机构才可以更好的理解索引的逻辑。其中以B+树为数据结构的索引最为重要,实际生活中我们默认索引就是通过B+树来实现的。因此我们要重点掌握好B+树的数据机构。

今天的内容到这里就结束了,感谢大家的阅读。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

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

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

相关文章

Linux,看这篇就够了

Linux 一、为什么要学linux二、目录介绍三、vi / vim编辑器四、网络配置4.1、修改 IP 地址4.2、配置主机名4.2.1、修改主机名称4.2.2、修改 hosts 映射文件 五、系统配置5.1、service 服务管理5.2、systemctl5.3、防火墙5.4、关机重启命令5.5、查看系统内核与版本 六、常用命令…

一分钟学一个 Linux 命令 - cat 和 tail

前言 大家好,我是 god23bin。今天我给大家带来的是 Linux 命令系列,每天只需一分钟,记住一个 Linux 命令不成问题。今天,需要你花费两分钟时间,因为我们要介绍的是两个常用的查看文件内容的命令:cat 和 ta…

动态规划-背包问题(三)

动态规划-背包问题(三) 1 描述2 样例2.1 样例 1:2.2 样例 2: 3 算法解题思路以及实现方法3.1 算法解题思路3.1.1 确定状态3.1.2 转移方程3.1.3 初始条件以及边界情况3.1.4 计算顺序 3.2 算法实现3.2.1 java实现的O(MN)算法复杂度3.2.2 C实现的O(MN)算法复…

Lua基本语法

目录 1 lua基础数据结构 2 Lua 变量 3 Lua 循环 3.1 Lua while 循环 3.2 Lua for 循环 数值for循环 泛型for循环 3.3 Lua repeat...until 循环 3.4 Lua 循环嵌套 3.5 循环控制语句 Lua break 语句 Lua goto 语句 4 Lua 流程控制 4.1 Lua if 语句 4.2 Lua if...else 语…

04-编织灵魂旋律:Golang 函数的魔力绽放

📃个人主页:个人主页 🔥系列专栏:Golang基础 💬Go(又称Golang)是由Google开发的开源编程语言。它结合了静态类型的安全性和动态语言的灵活性,拥有高效的并发编程能力和简洁的语法。G…

常见网络设备及其功能

1.常见网络设备及其功能 笔记来源: Computer network components and their functions 设备工作所在层隔离冲突域隔离广播域路由器(Router)网络层√√网桥(Bridge)数据链路层√交换机(Switch)数据链路层√中继器(Repeater)物理层集线器(Hub)物理层 1.1 路由器&…

chatgpt赋能python:Python并排输出数字——快速高效的实现技巧

Python并排输出数字——快速高效的实现技巧 在Python编程中,我们经常需要对数字进行输出,并排输出数字是一种非常常见的需求。比如说,我们需要将多个数据进行比较,或者需要将多个相关数据进行显示,等等。本文将介绍Py…

一.基于压缩感知(CS)的DOA估计方法-OMP-CS算法

阅读须知: 1.本文为本人原创作品仅供学习参考,未经过本人同意禁止转载和抄袭。 2.要想无障碍阅读本文需要一定的压缩感知理论以及压缩感知信号重构算法基础。 3.话不多说,直接开搞。 1 基于压缩感知DOA估计方法原理 假设有K个远场窄带信号…

dpdk21.11 编译(meson+ninja)及VFIO模块的加载和运行

目录 前言 安装前的环境配置 编译流程 1. 设置环境变量(好像也不需要了) 2. 构建dpdk 3. 编译 执行测试 1. 绑定vfio-pci 模块 2. 挂载网卡 3. 设置大页 4. 启动测试程序-testpmd 前言 操作系统:ubuntu22.04.2 LTS 内核版本&#…

深入理解 Java ServiceLoader、Dubbo ExtensionLoader 源码结合实战篇

介绍Java SPIDriver 实现类DriverManager 驱动管理器类loadInitialDrivers 方法registerDriver 方法getConnection 方法 ServiceLoader 核心类LazyIterator#hasNextService 方法LazyIterator#nextService 方法 Dubbo SPI加载策略FilterExtensionLoaderExtensionLoader#getExten…

框架篇面试详解

spring AOP AOP称为面向切面编程,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装成为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码&am…

02-舞动数据类型:Golang 类型定义的奇妙之旅

📃个人主页:个人主页 🔥系列专栏:Golang基础 💬Go(又称Golang)是由Google开发的开源编程语言。它结合了静态类型的安全性和动态语言的灵活性,拥有高效的并发编程能力和简洁的语法。G…

chatgpt赋能python:Python如何建设网页并实现客户端与服务器端的通信

Python如何建设网页并实现客户端与服务器端的通信 介绍 Python是一种流行的编程语言,被广泛应用于Web开发。在Web开发中,Python可以用来建立并联接网页与服务器端的通信。 这篇文章将介绍如何使用Python建立网页,并展示如何实现客户端与服…

Science Advance||个体脑中鲁棒的动态脑网络

文章目录 个体化动态方法(INSCAPE 方法):(A)生成脑共同激活状态的组模板:(B)个体水平分析: 不同的大脑状态有特定的协同激活模式(coactivation patterns&…

IntSet

基本概述 IntSet是Redis中set集合的一种实现方式,基于整数数组来实现,并且具备长度可变、有序等特征。 结构如下: typedef struct intset {uint32_t encoding; /* 编码方式,支持存放16位、32位、64位整数(4字节32比特…

chatgpt赋能python:Python如何并排输入数字

Python如何并排输入数字 Python是一个功能强大的编程语言,可以用于各种用途,包括数据分析、机器学习、Web开发等。对于很多初学者来说,学会如何并排输入数字可能是一个基础的技巧。在本文中,我们将介绍如何使用Python在同一行中输…

RK3588平台开发系列讲解(USB篇)USB 常用调试方法

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、USB枚举成功标志二、USB speed查询三、USB 查询PID、VID四、USB 当前 端口组合五、USB 动态打印debug日志六、USB IPC log分析沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇章主要 介绍 USB 常用调试…

安卓期末考试知识总结(2)

文章目录 第四章:程序活动单元Activity四大组件Activity生命周期Activity的启动模式standardsingleTopsingleInstancesingleTask IntentIntentFilterActivity之间的数据传递putExtra()方法传递数据Bundle类传递数据Activity之间的数据回传 练习总结 第四章&#xff…

Java虚拟机原理

Java是一种跨平台的语言,这意味着Java开发出来的程序经过编译后,可以在Linux上运行,也可以在Windows上运行;可以在PC、服务器上运行,也可以在手机上运行;可以在X86的CPU上运行,也可以在ARM的CPU…

chatgpt赋能python:Python引入Math库的使用方法

Python引入Math库的使用方法 Python作为一门强大的编程语言,有着广泛的应用场景。在计算领域中,Python也有很多优秀的库来进行相应的计算。其中一个广泛使用的库就是Math库。这个库包含了很多数学函数,如三角函数、幂函数、对数函数等等。在…