GOOD NIGHT

前言

上一篇中,我们已经了解到了索引的基本概念和一些用法。那索引为什么会提升查询的速度,以及索引究竟是怎么工作的呢?也许大家心里还是有一些迷茫,这一切,还要从索引背后的算法说起。

GOOD NIGHT

概述

大家知道数据库的索引和数据,一般都是存储在硬盘中的,这样利于数据的持久化和永久保存。因此在我们查找数据的时候,就会产生硬盘的I/O操作。而硬盘相较于内存而言,速度是比较慢的,所以如何减少硬盘的I/O操作,就是索引背后的算法存在的意义。

GOOD NIGHT

二分法

二分法是一种常用的查找算法,相较于逐个遍历查找而言,二分法的时间复杂度为O(log2n)。为了帮助大家理解和回忆二分查找,我画了一张二分查找的流程图:

从上述流程来看,我们要事先对要查找的数组或集合进行排序,而且每次会寻找中间节点进行范围的划分和对数字的比较。那么我们能不能把这个过程进行简化呢?二叉搜索树(Binary Search Tree)会给你答案。

GOOD NIGHT

二叉搜索树

如上文所述,二叉搜索树的特征是有序,且预先把数据进行分段存储,并且将中间节点作为树的根节点,那么我们会得到如下的二叉树结构,这里以数组[7,25,36,50,64,78,87]为例,创建出来的二叉树如下所示:

我们可以看出一些特征:对于每个节点而言,它的左孩子都小于它的父节点,而右孩子,都大于它的父节点。所以我们把这样的二叉树,叫做二叉搜索树(Binary Search Tree)。

二叉搜索树,重复利用了二分法的思想来查找数据,但有时由于构造树时产生问题,导致同样的数据插入顺序不一样,二叉搜索树就会变成如下结构:

从两张图的比较中我们不难看出,图一的树高度为3,也就是最多只需要3次比较,就能找出节点,而图二的树的结构会变成线性,需要7次比较,查找时的复杂度也会瞬间提升为O(n)。

所以为了解决二叉树不平衡的问题,人们又提出了新的数据结构,叫做平衡二叉搜索树(AVL树)

GOOD NIGHT

平衡二叉搜索树

刚才我们提出了,要解决二叉树的不平衡问题,就需要一个可以在每次插入或者删除节点时,都可以做到自动平衡的二叉树结构,也叫平衡二叉搜索树。

平衡二叉搜索树的核心思想就是计算每个节点的平衡因子(balance factor),平衡因子的定义是一个节点的左孩子的高度减去其右孩子的高度,这里的高度(height)就是指从一个节点出发到达最远叶子节点所经过的最长路径。如我们上述的图一中,从根节点50,到达子节点36的高度即为2。

通过上面的概念,我们可以发现,当一个节点的平衡因子绝对值大于等于1时,树就不再平衡,所以这里平衡二叉树还包含了一个旋转的机制,在此不表,感兴趣的同学可以自行查找进行理解。

那么我们在讲了这么多之后,平衡二叉搜索树是不是就可以作为索引背后的数据结构来进行存储了呢?这里再使用一张图来直观说明一下:

我们前文提到了查找数据是走了硬盘的I/O操作,那么对于这棵二叉树来说,树的高度为5,最坏的情况下,需要查找5次。这就意味着,如果树的高度越高,那么硬盘的I/O次数也会越多。

所以我们有没有办法去降低树的高度呢?可以遵循这样的思路去思考,如果一个节点下不止2个子节点,而是多个,那么整体的高度就可以降低。比如我们将二叉树,改为三叉树:

这个时候,同样的节点数量,我们的树高度则降为了4,也就是说,最多需要4次I/O即可找到需要查找的内容。

所以我们可以将二叉树改为M叉树(M>2),即一个节点下有M个子节点,这样当数据量大小为N时,M叉树的高度将会远远小于二叉树的高度,这样就引申出了B树的概念。

GOOD NIGHT

什么是B树?

B树的英文全名为Banlance Tree,翻译过来为平衡多路搜索树,我们从上文中已知,当一个节点有多个子节点时,高度会下降,因此B树很适合用于查询,在文件系统和数据库系统中的索引,常常会使用B树来实现。在这里有一个概念纠正下,有些书中或博客会提到B-树,而实际上B-树和B树是同一种结构,只是翻译名称上存在一些误解。

B树的结构如图所示:

B 树作为平衡的多路搜索树,它的每一个节点最多可以包括 M 个子节点,M 称为 B 树的阶。每个节点中,都存储了关键字和子节点的指针。对于一个 100 阶的 B 树来说,如果有 3 层的话最多可以存储约 100*100* 100=100 万的索引数据。

B树的特性有以下几点:

1、所有节点关键字是按递增次序排列,并遵循左小右大原则。

2、树中的每个节点至多有M个子节点,即至多有M-1个关键字(二叉树有2个子节点和1个关键字)。

3、除根节点外,其他节点至少有M/2个子节点。

4、若根节点不是叶子节点,则根节点至少有2个子节点。

5、所有叶子节点均在同一层,所以B树是一个所有平衡因子均为0的多路查找树。

以上图为例,根节点中有2个关键字:17和35,以及3个子节点指针:P1、P2和P3。而且在第二层最左侧的子节点中,有2个关键字8和12,包含了3个子节点。子节点1中的关键字为3和5,都小于8,而子节点2中的关键字为9和10,大于8小于12,子节点3中的关键字为13和15,均大于12,都符合我们上述提到的特性。

如果我们使用B树进行查找关键字9,那么可以分为以下几步:

1、先与根节点进行比较,9小于17,那么我们可以得到指针P1,继续从子节点中进行查找;

2、在子节点中,9大于8而小于12,此时可以得到指针P2,继续往下查找;

3、在最后一层的子节点中,找出关键字9,结束查找。

可以看出,相较于平衡二叉树而言,B树查找时的磁盘I/O要少,整体查询效率也要高出很多。看到这里相信大家已经大致明白了索引背后的工作原理,B树已经很适合作为索引的算法。但实际上,在MySQL中,还会使用B+树索引,这又是为什么呢?

GOOD NIGHT

B+树的改进

相较于B树而言,B+树在两个方面又做出了改进和提升,一方面是查询的稳定性,另一方面是查询的效率更高。

B+树的结构如下图所示:

与B树相比,B+树的非叶子节点不保存具体的数据,而只保存关键字的索引,所有的数据都会保存至叶子节点。因为所有数据必须要到叶子节点才能获取到,所以每次数据查询的次数都一样,这样一来B+树的查询速度也就会比较稳定。

在B+树中,非叶子节点的子节点数=关键字数,如上图所示,根节点有2个关键字,对于的也有2个子节点。这样的好处是一个节点可以存储更多的关键字,阶数会更大,高度会更低,查询效率也就更高。

B+树查找关键字的方式与B树类似,先从关键字中找出范围和指针,然后找到对应的子节点,一级一级往下查询,直到最终的叶子节点查出所需要的数据。

由于B+树的数据都存储在叶子节点,所以更有利于数据库做全表扫描,不需要像B树一样逐层扫描,而是直接遍历所有的叶子节点即可。

GOOD NIGHT

总结

今天我们从最基本的二分查找开始,逐步分析了各种查找树的工作原理和优缺点,不断改进,从而挖掘出最终的B树和B+树算法,深刻理解了索引背后的工作原理。虽然传统的二叉树查询的效率也很高,但是很容易增加磁盘I/O的次数,影响索引使用的效率,所以我们最终会采用降低树高度的方式来构造索引。

在实际工作中,我们使用索引也许不会直接去编写B树和B+树的算法。但是学习这些算法,会有助于我们增强逻辑思考的能力,还可以提升一些设计方面的能力,对于“修炼内功”会很有帮助,希望大家可以在这条路上持之以恒。

下一期将是索引系列的最终篇章,我们会结合实际工作中的复杂SQL场景,合理使用索引和改写原有语句以避免全表扫描来对数据库进行优化,敬请期待!

您的点赞和在看是我创作的最大动力,感谢支持

公众号:wacky的碎碎念

知乎:wacky

数据库性能系列之索引(中)相关推荐

  1. SQL Server 查询性能优化——覆盖索引(二)

    在SQL Server 查询性能优化--覆盖索引(一)  中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索 ...

  2. 数据库性能优化经验总结

    1.数据库访问优化法则 要正确的优化SQL,我们需要快速定位能性的瓶颈点,也就是说快速找到我们SQL主要的开销在哪里?而大多数情况性能最慢的设备会是瓶颈点,如下载时网络速度可能会是瓶颈点,本地复制文件 ...

  3. 死磕数据库系列(三十五):MySQL 数据库性能监控

    点关注公众号,回复"1024"获取2TB学习资源! 前面给大家介绍了:MySQL 性能分析与相关工具的使用.今天我将详细的为大家介绍 MySQL 性能监控的相关知识,希望大家能够从 ...

  4. mysql 改表面_MySQL_解析MySQL数据库性能优化的六大技巧,数据库表表面上存在索引和防 - phpStudy...

    解析MySQL数据库性能优化的六大技巧 数据库表表面上存在索引和防错机制,然而一个简单的查询就会耗费很长时间.Web应用程序或许在开发环境中运行良好,但在产品环境中表现同样糟糕.如果你是个数据库管理员 ...

  5. 程序员的算法课(16)-B+树在数据库索引中的作用

    前文讲了二叉树和多路树,二叉树的性能很好,像AVL树.红黑树都是很优秀的结构,那么在数据库索引中,并没有采用二叉树这种结构,这是为什么呢?因为,有性能更好的树来做搜索!目前大部分数据库系统及文件系统都 ...

  6. 一道面试题引出的系列数据库性能,数据安全问题及解决方案

    友情链接:http://enmotech.com/web/classify/43.html http://enmotech.com/web/classify/28.html 事件背景: SELECT ...

  7. MySQL数据库性能优化由浅入深(表设计、慢查询、SQL索引优化、Explain分析、Show Profile分析、配置优化)

    文章目录 0 SQL性能分析 1 表的设计合理化 1.1 为什么需要范式 1.2 三范式原理 1.3 什么样的表才满足三范式 2 慢查询 2.1 慢查询介绍 2.2 慢查询步骤 3 添加适当索引 3. ...

  8. 性能优化系列第一篇——数据库性能优化

    本文章转载的Trinea大神的文章,文章原地址 http://www.trinea.cn/android/database-performance/ 性能优化之数据库优化 本文为性能优化的第一篇--数 ...

  9. B树在数据库索引中的应用剖析

    引言 关于数据库索引,google一个oracle index,mysql index总 有大量的结果,其中很多的使用方法推荐,**索引之n条经典建议云云.笔者认为,较之借鉴,在搞清楚了自己的需求的基 ...

最新文章

  1. 在虚拟机上安装XP系统
  2. 配置Exchange Server 2010数据库高可用性组(DAG)
  3. html5调用系统声音1s响一次_20款奔驰GLC260提车改柏林之声音响,音乐诉请,为爱发声!...
  4. 更换计算机桌面背景的教案,桂科版三年级下册任务一 美化桌面背景免费教学设计...
  5. Opatch java 路径_Windows平台下opatch apply报错:OUI-67073
  6. ZOJ 1013 Great Equipment(DP)
  7. php mysql sqlite3_PHP连接SQLite数据库
  8. Java------String DAte 转化
  9. 计算机一级考试模拟软件安装方法,计算机一级考试软件怎么使用_计算机一级考试软件安装使用教程...
  10. 软件工程基础知识--软件项目管理
  11. 火电厂给水串级控制系统仿真
  12. mysql 计算信度_解析组合信度CR、AVE值如何计算_组合信度cr
  13. rs232接口_为什么越来越多人用RS232接口,却还分不清DB9、DB25的引脚定义?
  14. 《东周列国志》第四十四回 叔詹据鼎抗晋侯 弦高假命犒秦军
  15. 听说这个深度学习工具包,可以拯救Java开发者?
  16. PDF转图片哪个格式最清晰?PDF转高清图片的方法
  17. C++数学与算法系列之初等数论
  18. 【vivado学习六】 Vivado综合
  19. 大数据、云计算系统高级架构师课程学习路线图
  20. 汉芯一号诞生记 zz

热门文章

  1. 零基础小白python入门——深入Python中的文件操作
  2. 评论与回复数据表设计
  3. win10系统 删掉自带的输入法
  4. Kubernetes切换Docker容器引擎为Containerd
  5. Linux终端分屏软件tmux工具基本快捷键
  6. 态度决定高度,高度决定命运。对自己要狠一点,再狠一点,因为,你要的比别人多,就必须付出得比别人多。...
  7. java 月份间隔_java计算两个日期之间相隔的月份(向下取整)
  8. 什么是批标准化 (Batch Normalization)
  9. 广告大腕江南春:广告语是老板的责任
  10. mysql给所有表添加字段