热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MySQL(InnoDB剖析):InnoDB索引概述、数据结构与算法概述(二分查找、二叉搜索树、平衡二叉树、B+树)

一、索引概述索引是应用程序设计和开发的一个重要方面。若索引太多,应用程序的性能可能会受到影响。而索引太少,对查询性能又会产生影响。要找到一个平衡点二、InnoDB存储引擎索引概述I

一、索引概述

  • 索引是应用程序设计和开发的一个重要方面。若索引太多,应用程序的性能可能会受到影响。而索引太少,对查询性能又会产生影响。要找到一个平衡点


二、InnoDB存储引擎索引概述

  • InnoDB支持以下几种常见的索引:

    • B+树索引

    • 全文索引

    • 哈希索引


  • 前面已经提到过,InnoDB支持的哈希索引是自适应的InnoDB存储引擎会根据表的使用情况自动为表生成哈希索引,不能人为干预是否在一张表中生成哈希索引

  • B+树索引是传统意义上的索引这是目前关系型数据库中查找最为常见和最有效的索引。B+树索引的构造类似于二叉树,根据键值快速找到数据


  • 注意:B+树索引并不能找到一个给定键值的具体行。B+树索引能找到的只是被查找数据行所在的页。然后数据库通过把页读入内存,再在内存中进行查找,最后得到查找的数据


三、二分查找法

  • 二分查找法(binary search)也称为折半查找法,用来查找一组有序的记录数组中的某一记录,其基本思想是:将记录按有序化(递增或递减)排列,在查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小于该中点元素,则将待查序列缩小为左半部分,否则为右半部分。通过一次比较,将查找区间缩小一半








演示案例



  • 如有5、10、19、21、31、37、42、48、50、52这10个数,现在要从这10个树中查找48这条记录,其查找过程如下:


  • 从上图可以看到,用来3此就查找到了。如果是顺序查找,则需要8次。如果要查找5这条记录,顺序查找只需1次,二分查找法需要4次

  • 对于上面10个数来说,平均查找次数为(1+2+3+4+5+6+7+8+9+10)/10=5.5次。二分查找法为(4+3+2+4+3+1+4+3+2+3)/10=2.9次。在最坏的情况下,顺序查找的次数为10,而二分查找的次数为4




  • 二分查找法的应用及其广泛。在前面也介绍过,每页PAGE Directory中的槽是按照主键的顺序存放的,对于每一条具体记录的查询是通过对Page Directory进行二分查找的


四、二叉搜索树

  • 定义:

    • 二叉搜索树是一棵二叉树

    • 左子树的键值都小于父节点的键值

    • 右子树的键值都大于父节点的键值


  • 例如下面就是一颗二叉搜索树


查找复杂度



  • 查找5这个节点:

    • 那么先从跟查找,然后再查找左子树3,然后再查找右子树5,最终找到。一共找了3次

    • 如果通过中序遍历的话也需要3次


  • 查找8这个节点:

    • 先找6,再找7,再找8,最终找到。一共找了3次

    • 如果通过中序遍历的话需要6次


  • 总结:

    • 二叉树的平均查找次数为(3+3+3+2+2+1)/6=2.3次

    • 中序遍历的查找次数为(1+2+3+4+5+6)/6=3.3次

    • 因此,二叉搜索树的平均查找速度较快




五、平衡二叉树

  • 平衡二叉树是根据二叉搜索树改进的一种树,例如我们有2、3、5、6、7、8这几个节点,通过下图所示的结构来建立二叉查找树,图中的平均查找次数为(1+2+3+4+5+5)/6=3.16次。因此查找效率比较低


  • 平衡二叉树的定义:

    • 也是一颗二叉查找树

    • 但是左右子树的高度差最大为1,不能超过1,如果超过1,那么就不平衡了




单旋转


  • 在上图所示的平衡二叉搜索树中插入节点9,那么就不是平衡的了,因为节点7的的左右子树高度差为2


  • 因此需要做一次单旋转来回到平衡状态



双旋转


  • 在上图所示的平衡二叉搜索树中插入节点3,那么就不是平衡的了,因为节点2的的左右子树高度差为2


  • 因此需要做双旋转来回到平衡状态


六、B+树

  • B+树和二叉树、平衡二叉树一样,都是经典的数据结构。B+树由B树和索引顺序访问方法(ISAM,这就是MyISAM引擎最初参考的数据结构)演化而来,但是在实现使用过程中几乎已经没有使用B数的情况了

  • 下面我们对B+数进行精简的讲述:B+树是为磁盘或其他直接存储辅助设备设计的一种平衡查找树,由各叶子节点指针进行连接。先来看一个B+数,其高度为2,每页可存放4条记录,扇出(fan out)为5,图下图所示

  • 从下图可以看出,所有记录都在叶子节点上,并且是顺序存放的,如果用户最坐左边的叶子节点开始顺序遍历,可以得到所有键值的顺序排列:5、10、15、20、25、30、50、55、60、65、75、80、85、90


B+树的插入操作



  • B+树的插入必须保证插入后叶子节点中的记录依然排序,同时需要考虑插入到B+树的三种情况,每种情况都可能会导致不同的插入算法。如下图所示:

Leaf Page未满、Index Page未满的插入



  • 对于上面那张B+树所示,若用户插入28这个键值,因为Leag Page和Index Page都未满,因此可以直接插入,得到下图所示结果

Leaf Page已满、Index Page未满的插入



  • 接着上图,我们再插入70这个键值,此时Leag Page已满但是Index Page未满,插入之后Leaf Page的情况为:50、55、60、65、70,此时中间节点为60,以60来拆分叶子节点

  • 此时根据以下规则插入:

    • 查分Leaf Page

    • 将中间的节点(60)放入到Index Page中

    • 小于中间节点的记录(50、55)放左边

    • 大于或等于中间节点的记录(65、70)放右边


  • 最终的结果过如下图所示(备注:下图没有在各叶子节点加上双向链表指针,不过与上图一样,它是存在的):

Leaf Page已满、Index Page已满的插入



  • 接着上图,我们插入键值95,此时Leag Page、Index Page都已满,因此需要做两次拆分,执行步骤如下:

    • 拆分Leaf Page

    • 小于中间节点的记录放左边

    • 大于或等于中间节点的记录放右边

    • 拆分Index Page

    • 小于中间节点的记录放左边

    • 大于中间节点的记录放右边

    • 中间节点放入上一层Index Page




旋转操作



  • 从上面可以看到,不论B+树如何变化,最终都会平衡。因为B+树会不断进行拆分页操作。但是B+数主要用于磁盘,页的拆分意味着磁盘的操作,所以应该在可能的情况下尽量减少页的拆分操作,所以B+树也提供了类似于平衡二叉树的旋转操作

  • 原理:


    • 旋转发生在Leaf Page已满,但是其左右兄弟节点没有满的情况下

    • 这时B+树并不会急于去做拆分页的操作,而是将记录移动到所在页的兄弟节点上

    • 在通常情况下,左兄弟会被首先检查用来做旋转操作


  • 再来看看上面“Leag Page未满、Index Page未满的插入”,如下图所示:


  • 若插入键值70,其实B+树并不会急于拆分叶子节点,而是做旋转操作,得到下图所示的操作



B+树的删除操作



  • B+树使用填充因子(fill factor)来控制树的删除变化,50%是填充因子可设的最小值

  • B+树的删除操作同样必须保证删除后叶子节点中的记录依然排序

  • 同插入一样,B+树的删除操作同样需要考虑下面的3种情况,与插入不同的是,删除根据填充因子的变化来衡量

表中删除的第一种情况(删除节点为叶子节点)



  • 例如根据上图,我们要删除70这条记录。因为70为叶子节点,因此直接删除这个叶子节点即可

  • 最终的结果如下

表中删除的第一种情况(删除节点非叶子节点)



  • 接着上图,我们删除键值为25记录,但是该值还是Index Page中的值,因此删除之后要以其右兄弟节点(2)来代替。最终的结果如下

表中删除的第一种情况



  • 接着上图,我们要删除60这个节点

  • 删除Leaf Page中键值为60的记录后,File Factor小于50%,这时需要做合并操作,同样,再删除Index Page中相关记录后需要做Index Page的合并操作,最终的结果如下:






推荐阅读
  • PHP 编程疑难解析与知识点汇总
    本文详细解答了 PHP 编程中的常见问题,并提供了丰富的代码示例和解决方案,帮助开发者更好地理解和应用 PHP 知识。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 本文深入探讨了二叉搜索树(Binary Search Tree, BST)及其操作,包括查找、插入和删除节点。同时,文章还介绍了平衡二叉树(AVL树)的概念及调整方法,并详细讨论了如何判断两个序列是否构成相同的二叉搜索树。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
    本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ... [详细]
  • 深入理解C++中的KMP算法:高效字符串匹配的利器
    本文详细介绍C++中实现KMP算法的方法,探讨其在字符串匹配问题上的优势。通过对比暴力匹配(BF)算法,展示KMP算法如何利用前缀表优化匹配过程,显著提升效率。 ... [详细]
  • 在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ... [详细]
  • 在给定的数组中,除了一个数字外,其他所有数字都是相同的。任务是找到这个唯一的不同数字。例如,findUniq([1, 1, 1, 2, 1, 1]) 返回 2,findUniq([0, 0, 0.55, 0, 0]) 返回 0.55。 ... [详细]
  • 网络攻防实战:从HTTP到HTTPS的演变
    本文通过一系列日记记录了从发现漏洞到逐步加强安全措施的过程,探讨了如何应对网络攻击并最终实现全面的安全防护。 ... [详细]
  • MySQL中枚举类型的所有可能值获取方法
    本文介绍了一种在MySQL数据库中查询枚举(ENUM)类型字段所有可能取值的方法,帮助开发者更好地理解和利用这一数据类型。 ... [详细]
  • 本文探讨了在处理大量物联网设备时,如何合理设计关系型数据库来高效记录设备的上下线历史,确保数据的可维护性和扩展性。 ... [详细]
  • 如何在PHPCMS V9中实现多站点功能并配置独立域名与动态URL
    本文介绍如何在PHPCMS V9中创建和管理多个站点,包括配置独立域名、设置动态URL,并确保各子站能够正常运行。我们将详细讲解从新建站点到最终配置路由的每一步骤。 ... [详细]
author-avatar
寡凫lo单鹄官方
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有