HASH索引,AVL树,B树,B+树的区别?

1. 什么是 Hash

1.1 Hash 函数

Hash 本身其实是一个函数,又被称为散列函数,它可以大幅提高我们对数据的检索效率。因为它是散列的,所以在存储数据的时候,它也是无序的。

Hash 算法是通过某种确定性的算法(例如MD5,SHA1,SHA2,SHA3)将输入转变成输出,相同的输入结果永远会得到相同的输出。

1.2 Hash 碰撞

熟悉Java中 HashMap 的同学应该都知道,我们在往Map集合中存放元素的时候,它会先对要往集合中存放的元素的key值做一个哈希运算,从而确定它要存入的位置。理论上每一个对象都会存放在不同的地方,但当存放的对象越来越多时,有可能后来添加的元素的key值计算得出的结果与之前已经存入的元素的key的哈希值相等,这种现象就被称为哈希碰撞。当产生哈希碰撞的时候,我们会将后添加的元素与之前就已经存在的元素形成一个链表,当再次发生哈希碰撞时,就继续在链表尾部添加即可。

如下图所示,我们也可以采取这种方式将数据库中的数据以哈希的方式存储到哈希表中,可以看到h(k2)与h(k5) 就产生了哈希碰撞。

1.3 HashMap 的时间复杂度

我们知道,HashMap 其实就是一个数组,它是有下标的,我们在 查询/删除/修改 元素的时候,都可以直接通过哈希函数计算出来的哈希值精确到某个元素的位置,这里我们不考虑哈希碰撞形成的链表,因此 HashMap 的查询/删除/修改 元素的时间复杂度都是O(1),也就是常量级别的,可以说是非常非常快。

2. AVL树

2.1 简单了解AVL树

AVL树,其实也叫平衡二叉树,或叫平衡二叉搜索树,它通常满足一个特点,左子节点的值都比父节点小,右子节点的值都比父节点大,如下图所示

在这种情况下,我们去寻找数据91,只需要查找三次即可得出结果。

2.2 AVL树的时间复杂度

从上面我举得例子不难看出,在AVL树中查找数据时,每查找一次,砍掉一半的数据,再查找一次,再砍掉一半的数据,所以不难看出,AVL树的时间复杂度是 O(log2n)。

2.3 AVL树的缺点

AVL树时间复杂度虽然低,但也存在一些缺点,因为AVL树要保持高度的平衡,所以需要经常性旋转,旋转也是非常耗费时间,并且,随着数据越来越多,AVL树的深度也会越来越大,如下图所示,当数据达到31个的时候,树的高度已经有5层了。我们知道,每多一层,与磁盘就要多进行一次IO操作,非常耗费时间,所以我们就在想,能不能把树的高度降低一些,但同时又能存足量的元素呢?这就有了下面要说M叉树,也可以理解为B树。

3. B 树

经过了上面对AVL树的分析,我们也知道了,当树的叉越多时,存储的数据也越多,与磁盘交互的次数也越少,我们把上方的二叉树转换成三叉树,当然也可以转换成四叉树,五叉树都是可以的,这里我就以三叉树为例。

这个时候,我们还是能存储31个元素,并且树的高度由原来的5层降低到了4层,提高了我们数据的查找效率,这就是我们索引的雏形,我们就可以将数据库中的数据存储在树中,得到如下简易模型

上图中就是索引最开始形成的B树结构图,左上角也有标注,这个时候我们可以看到,在原始B树中,磁盘块1234这几个非根节点中还存放着数据呢,P1是地址值指向磁盘块2,并且里面记录的主键值都是小于26的;P3是地址值指向磁盘块4,里面记录的数据主键值都是大于35的;P2是地址值指向磁盘块3,里面记录的数据主键值都是在26与35之间的。下方的磁盘块2,3,4中都是同理,依次往下类推。

这种数据的存储方式和查找方式性能已经非常优秀了,但是还有一个缺点,我们将原来的2叉树转变成M多叉树,目的就是为了存储更多的数据,但大家看,在磁盘块2,3,4中,P1,P2,P3都是指针,不会占用多少空间,但8和12的data存储的是真实的数据,会占用部分磁盘空间,而且这个时候还有分成了三段,如果分的段更多,也会存储更多的数据,这就会导致我们无法存储更多的指针数据,违背了我们的初衷。于是,我们就可以对这个B树做进一步的升级(当然也不只是因为这一个原因,后面我们还会说到,这里先说这一点就)演化成了我们现在的 B+ 树结构。

4. B+ 树

如上图所示,就是从B树演化形成的 B+ 树,在 B+ 书中,我们舍弃了B书中非叶子节点也存储真实数据做法,将所有的真实数据全部存放在叶子节点中,这样我们的目录页就可以存放更多的指针数据。并在每一页都会添加一个数组,数组中记录着该页中的所有元素并按照从小到大的顺序排列。

例如上图,顶层目录页33记录了数据1,320,下方对应着页30与页33的地址值;中间目录页30中存储着 1,5,12,209,数据下方各自对应着该页的地址值;当我们想要查找(100,9,x)这条数据时,做判断,发现(100,9,x)的相关信息应存储在中间页30中,在进入中间页30寻找,经过判断发现该数据存放在页9中,根据对应的地址值找到页9,然后在页9中就可以获取到数据(100,9,x)了,不管查询那个数据,都是这样的一个过程,查询速度非常稳定,并且中间目录页不存储真实数据只存储地址值,可以存储更多的叶子节点页数据。

5. 为什么不采用哈希表存储数据呢?

这其实是一个面试题,刚才我们也分析过了,哈希表的时间复杂度为O(1),常量级别,是最快的,那么数据库存储数据时为什么不采用哈希表的形式存储呢?原因有以下几点:

(1)范围查找显得无力

如果我们采用哈希表的结构存储,你会发现,它只能满足我们对精准值得查找,当我们在数据库中加入了BETWEEN...AND...或IN这些范围查找关键字的时候,哈希表就没有优势了,而且哈希表还是乱序的,这就导致我们在进行范围查找时,时间复杂度为会从O(1)退化成O(n),而我们的树形结构时间复杂度稳定在O(log2n),这个时候我们就会发现,哈希表就没有优势了。

(2)排序浪费时间

因为哈希表是乱序存储,当我们需要进行ORDER BY 的时候,每次ORDER BY底层都要排一次序,而我们的树形结构在存储是就是有序的,不管什么时候取数据都省去了排序的时间。我们存储。

(3)不太支持联合索引

我们知道,B+树中是支持联合索引的,并会对多因进行排序,如果我们使用哈希表存储数据,当我们将字段C1与字段C2联合作为主键时,哈希存储就会把C1和C2作为一个整体计算哈希值,不会单个做哈希值计算。这样就乱套了,因为两个不一样的字段加在一起哈希值是可能相同的。

(4)索引列重复时效率低

我们知道计算哈希值就是为了避免哈希碰撞,如果一些字段肯定会出现碰撞,例如性别,年龄这些字段,那么哈希碰撞的概率就会非常大,它会遍历哈希桶中的每一个元素作比较,非常耗时,所以哈希索引通常不会用在容易出现重复的字段上。

6. 自适应 Hash 索引

在 InnoDB 引擎中,虽然本身不支持哈希索引,但是它提供了一个自适应的哈希索引,这个是默认开启的,当我们经常性地对数据库中的同一些数据做查询操作时,它就会将这些数据存放到哈希表中,以便我们以后更加快速的查找。

经过自适应哈希索引优化之后,之前我们需要进行一层层目录的查找,但是哈希表就可以让我们一步到位,省去检索的时间。

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

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

相关文章

virtualBox桥接模式下openEuler镜像修改IP地址、openEule修改IP地址、openEule设置IP地址

安装好openEuler后,设置远程登入前,必不可少的一步,主机与虚拟机之间的通信要解决,下面给出详细步骤: 第一步:检查虚拟机适配器模式:桥接模式 第二步:登入虚拟机修改IP cd /etc/sysconfig/network-scripts vim ifcfg-enpgs3 没有vim的安装或者用vi代替:sudo dnf …

关于consul的下载方法

linux下 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo sudo yum -y install consulwindow下 https://developer.hashicorp.com/consul/downloads 然后把里面的exe文件放在gopath下就行了 验证…

打造专属花店展示小程序

在当今社会,微信小程序已经成为了各行各业拓展客户资源的利器,而花店行业也不例外。通过打造一个独特的花店小程序,你可以为你的花店带来更多的曝光和客户资源。那么,如何制作一个专属的花店小程序呢?下面我们就来一步…

图像像素梯度

梯度 在高数中,梯度是一个向量,是有方向有大小。假设一二元函数f(x,y),在某点的梯度有: 结果为: 即方向导数。梯度的方向是函数变化最快的方向,沿着梯度的方向容易找到最大值。 图像梯度 在一幅模糊图…

【实际开发19】- 压测 / 调优准备

目录 1. Jmeter 2. Jmeter 环境部署 1. 配置 : 临时修改语言 ~ Options → Choose Language → Chinese 3. Jmeter 并发测试 0. 提示 : Postman 测试是“串行”的 , 无法测试并发请求 1. daiding 1. Jmeter 下载 : Apache JMeter - Download Apache JMeter 详参&#xf…

【已解决】mac端 sourceTree 解决remote: HTTP Basic: Access denied报错

又是在一次使用sourcetree拉取或者提交代码时候,遇到了sourcetree报错; 排查了一会,比如查看了SSH keys是否有问题、是否与sourcetree账户状态有问题等等,最终才发现并解决问题 原因: 因为之前公司要求企业gitlab中…

JavaEE初阶:多线程 - 编程

1.认识线程 我们在之前认识了什么是多进程,今天我们来了解线程。 一个线程就是一个 "执行流". 每个线程之间都可以按照顺讯执行自己的代码. 多个线程之间 "同时" 执行 着多份代码. 引入进程这个概念,主要是为了解决并发编程这样的…

编译工具:CMake(三)| 最简单的实例升级

编译工具:CMake(三)| 最简单的实例升级 前言过程语法解释ADD_SUBDIRECTORY 指令 如何安装目标文件的安装普通文件的安装:非目标文件的可执行程序安装(比如脚本之类)目录的安装 修改 Helloworld 支持安装测试 前言 本篇博客的任务…

解决右键打印html只能识别1页的问题

hello,大家好久不见,昨天在开发中遇到了一个问题,就是在自己开发的网页中右键-->打印,由于页面内容过多,打印出来的内容只被识别到一页。 针对这一问题,查阅了好多资料最终解决啦。 1.问题重现 大家可以看到这个是我们开发的页面,公司需要…

2023最新最全最细版本~ESP8266/ESP01S烧录AT固件

硬件准备 图上有两种型号的模块均可刷写AT固件 ① ESP01S ② ESP8266NODEMCU 软件准备(私聊免费分享) ESP01S1烧录方式 如图使用模块烧录座的方式~ 模块插入烧录座后直接连接电脑的USB接口即可~ ESP8266NODEMCU烧录方式 如图usb直接连接的方式~ 一端接模块的USB口&…

数据暴涨时代,该如何数据治理?_光点科技

随着信息技术的迅猛发展,数据已经成为现代社会的核心资源。在这个被称为"数据暴涨时代"的时代里,大量的数据源源不断地被产生和积累,但如何有效地管理、分析和利用这些数据成为了一个迫切需要解决的问题。数据治理,作为…

【Spring源码】Spring扩展点及顺序

Spring扩展点及顺序 01-调用BeanFactoryPostProcessor的构造器 02-调用了BeanFactoryPostProcessor的postProcessBeanFactory 03-调用了BeanPostProcessor构造器 04-调用InstantiationAwareBeanPostProcessor构造方法 05-调用了InstantiationAwareBeanPostProcessor接口的Befo…

Memory Analyzer(MAT)分析内存

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 目录 一、导读二、概览三、 使用3.1 hprof 文件准备3.1.1 Android sutdi…

【SpringBoot学习笔记】04. Thymeleaf模板引擎

模板引擎 所有的html元素都可以被thymeleaf替换接管 th:元素名 templates下的只能通过Controller来跳转,templates前后端分离,需要模板引擎thymeleaf支持 模板引擎的作用就是我们来写一个页面模板,比如有些值呢,是动态的&#x…

cuda+anaconda+pytorch按照教程

首先安装显卡对应的CUDA版本,关键点在于区别显卡支持的CUDA最高版本和运行版本 1、查看当前显卡支持的最高版本,有两种方式: 1)NVIDIA控制面板—>帮助—>系统信息—>组件—>NVCUDA.dll对应版本 请注意,12…

2023年国赛数学建模思路 - 案例:ID3-决策树分类算法

文章目录 0 赛题思路1 算法介绍2 FP树表示法3 构建FP树4 实现代码 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法,就是频繁模…

项目:基于UDP的TFTP文件传输

1)tftp协议概述 简单文件传输协议,适用于在网络上进行文件传输的一套标准协议,使用UDP传输特点: 是应用层协议 基于UDP协议实现 数据传输模式 octet:二进制模式(常用) mail:已经不再…

分布式 - 服务器Nginx:一小时入门系列之代理缓冲与缓存

官方文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html 1. 代理缓冲 proxy_buffer 代理缓冲用于临时存储从后端服务器返回的响应数据。通过使用代理缓冲,Nginx可以在接收完整的响应后再将其发送给客户端,从而提高性能和效率…

照耀国产的星火,再度上新!

国产之光,星火闪耀 ⭐ 新时代的星火⭐ 多模态能力⭐ 图像生成与虚拟人视频生成⭐ 音频生成与OCR笔记收藏⭐ 助手模式更新⭐ 插件能力⭐ 代码能力⭐ 写在最后 ⭐ 新时代的星火 在这个快速变革的时代,人工智能正迅猛地催生着前所未有的革命。从医疗到金融…

【管理运筹学】第 5 章 | 整数规划 (1,问题提出与分支定界法)

文章目录 引言一、整数规划问题的提出1.1 整数规划的数学模型1.2 整数规划问题的求解 二、分支定界法2.1 分支与定界2.2 基本求解步骤(一)初始化(二)分支与分支树(三)定界与剪枝(四)…