Mysql索据-Mysql的innodb引擎为什么要使用b+tree作为索引数据结构?

news2024/11/15 23:35:23

目录

索引?

什么是索引?索引有什么优点?索引有什么缺点?

索引的分类

按照功能分类:

按照数据结构分类

相关数据结构(b-tree、b+tree)

b-tree

b+tree

 b-tree和b+tree的区别

为什么Innodb要选择B+tree作为数据结构

索引常见问题

什么是聚簇索引?何时使用聚簇索引与非聚簇索引

联合索引是什么?为什么需要注意联合索引中的顺序?

 b+tree中innodb不需要回表查询吗?myisam一定会回表查询吗?

什么情况使用了索引,查询还是慢

什么情况下适合建索引什么适合下不适合建索引?


索引?

什么是索引?索引有什么优点?索引有什么缺点?

索引:索引是帮助mysql高效获取数据排好序的数据结构,一般来说索引本身也很大,不能全部存在内存中,因此索引往往保存在硬盘中

优点:提高了检索效率,降低了数据io成本,通过索引对数据进行排序,降低了数据排序的成本,降低了cpu的消耗

缺点:虽然索大大提高了查询速度,但是同时降低了更新表的速度,比如对表进行更新了之后,mysql不仅要更新数据,还要更新索引文件

索引的分类

按照功能分类:

  • 普通索引:最基本的索引,没有任何限制
  • 唯一索引:索引列的值必须唯一,但允许空,如果是组合索引,列值组合必须唯一
  • 主键索引: 一种特殊的唯一索引,不允许空,在建表时主键列同时创建主键索引
  • 联合索引:  将单列索引进行组合
  • 外键索引:只有InnoDB支持,用来保证数据一致性,完整性和实现级联操作
  • 全文索引:快速匹配全部文档的方式,innodb5.6版本后才支持。memory不支持

按照数据结构分类

  • B Tree索引:Mysql使用最频繁的索引,是Innodb和myisam存储引擎默认的索引类型,底层是基于b+tree
  • hash索引:  Mysql中menmory存储引擎默认支持的索引类型

相关数据结构(b-tree、b+tree)

b-tree

说明:上图中每一个黑色方块为一个磁盘块,P代表指向下一节点的指针,D代表携带的数据,蓝色方块中的数字代表键。

                Btree是一种多路查找树,Btree中所有节点的子树个数的最大值为Btree的阶,如上图中每一个节点的子树最大值为3,所以是一颗3阶树,一个m阶的Btree如果不为空,就必须具备以下性质: 

  • 树中每个结点至多有m-1个关键字,即m棵子树。
  • 树中可看到真实存在的最后一排为终端节点而非叶子节点,叶子节点实际不存在,是btree查询时候为空的情况,上图中3、5、9、10等这一排实际是终端节点。
  • 除根节点以外,所有的非叶节点至少含有(m/2)-1个关键字,m/2棵子树
  • 根节点关键字可以小于(m/2)-1个,可以没有子树,如果有子树,则至少有两棵子树
     

b+tree

说明:一个m阶的B+tree如果不为空,就必须满足以下特性:

  • 树种每个节点至多含有m个关键字,m棵子树(节点的关键字和子树相同)
  • 除根节点外,所有非叶节点至少含有m/2个关键字,m/2棵子树
  • 根节点的关键字个数可以小于m/2,可以没有子树,如果有子树,至少有两棵
  • 所有叶结点中包含了全部关键字和关键字指向记录的指针,叶节点内的关键字也是有序排列的,叶节点之间也是有序排列的,指针相连,实际是个双向链表
  • 所有的非叶节点仅仅携带关键字和指向下一节点的指针
  • B+tree分为聚集索引和非聚集索引,如果是聚集索引的话,叶子节点存放的是一整行记录的数据。如果是非聚集索引的话,仅仅存放着主键,还要通过主键回表查询那一行记录的数据
     

 b-tree和b+tree的区别

以m阶树表示

  • B+tree由分块查找进化而来,B树由二叉排序树进化而来
  • 在B+tree中每个非根节点的关键字数的取值范围是m/2<= n<=m,子树个数为n;在Btree中每个非根节点的关键字树的取值范围是(m/2)-1<=n<m-1,子树个数为n+1
  • 在B+tree中,只有叶节点包含信息,非叶节点只起到索引所用;Btree中全部节点的关键字都包含信息
  • 在B+tree中,叶节点包含了全部关键字,非叶节点中出现的关键字一定会出现在叶节点中;在Btree中,任何节点中的关键字都不会重复
  • B+tree支持顺序查找和多路查找,Btree只支持多路查找
  •  B+tree中,查找成功或失败都会到达最后一层(叶子节点);而Btree中查找成功时,随时停止搜索。
  • B+tree的叶子节点有一条链相连;Btree中终端节点各自独立
  • 增删文件(节点)时,效率更高。因为B+树的叶子节点包含所有关键字,并以有序的链表结构存储,这样可很好提高增删效率。
     

为什么Innodb要选择B+tree作为数据结构

  • B+tree每次都要访问叶子节点,遍历层次来看更加的稳定
  • b+tree的叶子节点使用指针连接在一起,方便了顺序遍历,既能满足范围查找又能满足多路查找
  • B+Tree 只需要去遍历叶子节点就可以实现整棵树的遍历
  • B+Tree 的非叶子节点并没有保存关键字的具体数据信息,内部节点相对B-Tree更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了

索引常见问题

什么是聚簇索引?何时使用聚簇索引与非聚簇索引


聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因
密集索引和稀疏索引对应聚簇索引和非聚簇索引
 

联合索引是什么?为什么需要注意联合索引中的顺序?

联合索引:MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。

为什么要注意排序?

MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。

当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用做索引查找,以此类推。因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。

如上图所示他们是按照a来进行排序,在a相等的情况下,才按b来排序。

因此,我们可以看到a是有序的1,1,2,2,3,3。而b是一种全局无序,局部相对有序状态!什么意思呢?

从全局来看,b的值为1,2,1,4,1,2,是无序的,因此直接执行b = 2这种查询条件没有办法利用索引。

从局部来看,当a的值确定的时候,b是有序的。例如a = 1时,b值为1,2是有序的状态。当a=2时候,b的值为1,4也是有序状态。因此,你执行a = 1 and b = 2是a,b字段能用到索引的。而你执行a > 1 and b = 2时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段用不上索引。

综上所示,最左匹配原则,在遇到范围查询的时候,就会停止匹配。
 

 b+tree中innodb不需要回表查询吗?myisam一定会回表查询吗?

都不一定,先说innodb,在innodb中主键索引是采用聚簇索引的形式有以下三种情况

  1. 如果通过主键查找,那么命中的时候,主键索引中就会包含那一行记录,就不用回表查询
  2. 实现覆盖索引,当通过联合索引查询是,查询的数据刚好是联合索引的列,就不用回表查询,例如select name,age from student where name=‘zhangsan’ and age=18,联合索引(name,age) ,这种情况就不用回表,因为查找的内容就是索引本身
  3. 如果通过普通查找所有列例如select * from student where name=‘zhangsan’,索引为name,这时候是需要回表查询的

再说myisam,myisam中都是非聚簇索引,所以仅仅当实现索引覆盖的时候不用回表,其他情况都需要回表查询

什么情况使用了索引,查询还是慢

  • 索引全表扫描
  • 索引过滤性不好
  • 频繁回表的开销

什么情况下适合建索引什么适合下不适合建索引?

适合建立索引的情况

  •  主键自动创建索引
  •  频繁作为查询条件的字段应该创建索引
  •  查询中与其他表关联的字段,外键关系建立索引
  •  排序和分组的字段

 
不适合建立索引的情况

  •   频繁增删改的字段不适合创建索引
  •  where条件里的字段不适合创建索引
  •  数据重复且分布均匀的数据。
  •  表的记录过少(建立索引无意义)
     

b+tree中3层树高能存储多少条数据?


假设每个索引使用的是bigint,占8个字节,然后指针占6个字节,也是说第一层中一个索引就占了14个字节,而mysql中有页的概念,一页大小为16kb。第一次能存放的索引就是16kb/14b=1170个,而第一个节点中有1170个索引,也就意味着能有1170棵子树,也就是说第一第二成存放的索引为1170*1170=1368900个,在第三层中,如果是用的innodb的话,假设表中每一行数据1kb,也就是一页能存放16个索引。那么总数就是1170*1170*16=21,902,400个。约为两千万条数据。

innodb通过索引查询数据中比较耗时的是哪一步?
 

最耗时的一步是将数据从磁盘读取到内存中的这一步,而数据读取到内存中会进行比较与筛选。那么问题来了,为什么不一次性将所有的数据都读取到内存进行比较筛选呢?如果我们数据库中的数据量非常非常大的时候,一次行将所有的数据读取到内存,就会出现两个极端问题

  1. 内存占用严重,甚至会出现内存溢出的问题
  2. 过大量的数据同时进行比较,效率也不一定会高

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

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

相关文章

65. 锚框的代码实现

目标检测算法通常会在输入图像中采样大量的区域&#xff0c;然后判断这些区域中是否包含我们感兴趣的目标&#xff0c;并调整区域边界从而更准确地预测目标的真实边界框&#xff08;ground-truth bounding box&#xff09;。 不同的模型使用的区域采样方法可能不同。 这里我们…

TiDB学习笔记(八)-数据库故障处理

一、数据丢失快速恢复 数据恢复前置条件-GC&#xff0c;tidb_gc_life_time 查询GC已经清理的时间点tikv_gc_safe_point 数据快速恢复操作方式 DML->tidb_snapshot参数 &#xff08;在tikv_gc_safe_point范围内&#xff09; DDL->flashback table/recover table (flas…

AIGC与搜索深度融合,百度定义“生成式搜索”

设想一下&#xff0c;当你搜索“公司活动通知怎么写”时&#xff0c;搜索引擎直接“写”了一篇送到眼前是什么体验&#xff1f;百度的“生成式搜索”正在让这样的场景成为现实。日前&#xff0c;百度宣布&#xff0c;百度搜索将升级“生成式搜索”能力&#xff0c;基于百度自研…

项目管理工具dhtmlxGantt甘特图入门教程(七):在服务器上使用甘特图

dhtmlxGantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表&#xff0c;可满足项目管理控件应用程序的所有需求&#xff0c;是最完善的甘特图图表库。 这篇文章给大家讲解如何在服务器上使用DHTMLX Gantt 。 DhtmlxGantt正版试用下载&#xff08;qun&#xff1a;764…

Cadence PCB仿真使用Allegro PCB SI元器件类别设置为IO,IC和Discrete的方法图文教程

⏪《上一篇》   🏡《总目录》   ⏩《下一篇》 目录 1,概述2,配置方法3,总结1,概述 本文简单介绍使用Allegro PCB SI软件配置电压地网络电压的方法。 2,配置方法 第1步:打开待仿真的PCB文件,并确认软件为Allegro PCB SI 如果,打开软件不是Allegro PCB SI则可这样…

ElementUI源码系列一-完整引入和按需引入

前言 本篇将介绍&#xff0c;ElementUI 是如何实现完整引入和按需引入的。 完整引入 官网使用 源码步骤 src/index.js 通过对外暴露 install()&#xff0c;让主项目通过 Vue.use(ElementUI) 引入&#xff0c;还需单独引入样式 import element-ui/lib/theme-chalk/index.c…

Selenium用法详解【Options选项】【JAVA爬虫】

简介本文主要讲解如何使用java代码利用selenium控制浏览器的启动选项Options的代码操作教程。Options选项这是一个Chrome的参数对象&#xff0c;在此对象中使用addArgument()方法可以添加启动参数&#xff0c;添加完毕后可以在初始化Webdriver对象时将此Options对象传入&#x…

minio分布式存储的go语言开发衔接

minio是分布式存储&#xff0c;可集群部署&#xff0c;阵列磁盘&#xff0c;纠错码等大数据存储必备的技术。由于它是go语言开发的&#xff0c;我们用go来与它衔接&#xff1a;上传文件&#xff0c;比如图片&#xff0c;然后预览。这里涉及几个重要的知识点。一是minio永久路径…

Vue学习笔记(二)

Vue学习笔记二脚手架利用脚手架软件生成项目包脚手架 随着时代的发展, WEB开发逐渐出现了 工程化 特征: 流水线作业! 脚本方式: 到饭店 自选点餐… 脚手架方式: 点 套餐, 一套完善的配置,扩展, 各种易用功能… 脚手架: 就是一款软件, 可以按照用户需求自动生成 开发环境: 包含…

[博士论文]基于图数据的可信赖机器学习

密歇根大学Towards Trustworthy Machine Learning on Graph Datahttps://deepblue.lib.umich.edu/handle/2027.42/174201摘要机器学习已经被应用于越来越多影响我们日常生活的与社会相关的场景&#xff0c;从社交媒体和电子商务到自动驾驶汽车和刑事司法。因此&#xff0c;为了…

7-2 洛希极限

科幻电影《流浪地球》中一个重要的情节是地球距离木星太近时&#xff0c;大气开始被木星吸走&#xff0c;而随着不断接近地木“刚体洛希极限”&#xff0c;地球面临被彻底撕碎的危险。但实际上&#xff0c;这个计算是错误的。 洛希极限&#xff08;Roche limit&#xff09;是一…

用Python实现十大经典排序算法(附动图)

排序算法是《数据结构与算法》中最基本的算法之一。 排序算法可以分为内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。常见的内部排…

69、CLIP-NeRF: Text-and-Image Driven Manipulation of Neural Radiance Fields

简介 官网&#xff1a;https://cassiepython.github.io/clipnerf/ 利用对比语言-图像预训练(CLIP)模型的联合语言-图像嵌入空间&#xff0c;提出了一个统一的框架&#xff0c;可以用短文本提示或示例图像以用户友好的方式操纵NeRF。改论文结合NeRF的新视图合成能力和生成模型潜…

【自学Python】Python缩进规则

Python缩进规则 Python缩进规则教程 Python 和其它程序设计语言采用大括号 {} 分隔代码块不同&#xff0c;Python 采用代码缩进和冒号来区分代码块之间的层次。 在 Python 中&#xff0c;对于 类定义、函数定义、流程控制语句、异常处理语句 等&#xff0c;行尾的冒号和下一…

【Linux篇】之TFTP服务配置

tftp是基于UDP协议的简单文本文件传输协议&#xff1b; 用途&#xff1a;使用网络的方式将文件传输(下载)到开发板中。 具体的tftp服务的安装步骤&#xff1a; 1> 安装tftp服务 (ubuntu必须可以上网) sudo apt-get update ----> 更新源 sudo apt-get install tftpd-hpa…

【MyBatis】如何使用“动态SQL”(不用找了,这一篇足矣)

目录 一、if标签 二、where标签 三、trim标签 四、choose、when、otherwise 五、foreach标签 六、sql标签 一、if标签 if&#xff0c;通过test属性中的表达式判断标签中的内容是否有效&#xff08;有效才将if里面的内容拼接到sql中&#xff09;&#xff1b;一般用于用户在…

Authing 通过中国信通院「身份治理系统和工具能力」全面级评估

Authing 通过中国信通院「身份治理系统和工具能力」全面级评估 近期&#xff0c;Authing 荣获由中国信通院颁发的「身份治理系统和工具能力」全面级评估。在统一身份管理、统一认证管理、开发集成管理以及统一安全管理四个模块满足身份治理系统和工具支撑能力全面级要求。 评估…

Java--main()方法

文章目录一、main()方法使用二、mian()方法调用一、main()方法使用 1、访问控制权限是公有的&#xff08;public&#xff09; 2、main() 方法是静态的。如果要在 main() 方法中调用本类中的其他方法&#xff0c;则该方法也必须是静态的&#xff0c;否则需要先创建本类的实例对…

进程间通信【共享内存】

共享内存共享内存共享内存原理创建共享内存关联共享内存去关联共享内存控制共享内存使用共享内存代码共享内存 进程间通信的前提是&#xff1a;先让不同的进程&#xff0c;看到同一份资源 之前&#xff0c;管道进程通信是采用看到同一个文件&#xff0c;那么共享内存就是看到同…

审查 Git 仓库的绝佳工具Tig

简介 Tig 是一个 基于 ncurses 的 Git 文本模式界面&#xff0c;它允许你浏览 Git 仓库中的更改。它还可以充当各种 Git 命令输出的分页器。使用这个工具可以让我很好地了解在哪个提交中发生了哪些更改&#xff0c;最新的提交合并是什么等等。 git工作原理&#xff1a;https:…