MySQL为什么使用B+树为索引结构

news2024/11/24 18:45:29

目录

1、什么是索引

2、索引的类型

3、为什么要用索引

4、索引的使用场景

5、索引为什么要用B+树,为什么不能用二叉树、红黑树、B树?

介绍一款可以帮助理解数据结构的网站(很好用):Data Structure Visualization

5.1 二叉查找树

5.2 红黑树(平衡二叉查找树)

5.3 B树

5.4 B+树

         5.5 Hash

6、哪些情况索引会失效?


1、什么是索引

索引是为了加速对表中数据行的检索而创建的一种分散的存储结构。索引是针对表而建立的,它是由数据页面以外的索引页面组成的,每个索引页面中的行都会含有逻辑指针,以便加速检索物理数据。(百度定义)

索引(index)是帮助MySQL高效获取数据的数据结构。(MySQL官方)

通俗的讲索引就是一个目录,为了方便快速的查找书中内容,是一个文件,要在磁盘中占用物理空间的。

2、索引的类型

维度索引名称关键字特点索引介绍
逻辑维度普通索引index可以多个 ​​基本​​的索引类型,值可以为空,没有唯一性的限制。
唯一索引unique 可以多个索引列的所有值都只能出现一次,即必须​​唯一​​,值可以为​​空​​。
主键索引primary默认自动创建,只能一个主键是一种唯一性索引,但不能为空,但它必须指定为​​ PRIMARY KEY​​,每个表只能有一个主键。
全文索引fulltext可以多个

全文索引的索引类型为​​FULLTEXT​​。
全文索引可以在​​varchar、char、text​​类型的列上创建。
可以通过​​ALTER TABLE​​或CREATE INDEX命令创建。
对于大规模的数据集,通过ALTER TABLE(或者CREATE INDEX)命令创建全文索引要比把记录插入带有全文索引的空表更快。
MyISAM​​支持全文索引,​​InnoDB​​在mysql5.6之后支持了​​全文索引​​。

全文索引​​不支持中文​​​需要借​​sphinx(coreseek)​​​或​​迅搜<、code>技术处理中文。​​

数据结构维度B+树索引所有数据存储在叶子节点,复杂度为O(logn),适合范围查询。
哈希索引适合等值查询,检索效率高,一次到位。
全文索引
R-Tree索引用来对GIS数据类型创建SPATIAL索引
物理存储维度聚集索引以主键创建的索引,叶子节点上存储该表中的所有数据行记录。
非聚集索引以非主键创建的索引,叶子节点存储的是主键和索引列。


 

聚集索引的优点:
查询通过聚集索引可以直接获取数据,相比非聚集索引需要第二次查询(非覆盖索引情况下)效率高
对范围查询效率很高,因为数据是按照大小排列的
适合排序的场景,非聚集索引不适合
聚集索引的缺点:
维护索引代价很高,特别插入新行或者更新主键导致导致页的分裂
如果主键是随机ID(比如UUID),导致存储稀疏(磁盘碎片),可能比全表扫描还慢,或者主键比较大,导致辅助索引变的很大(节点占用更多的物理空间),这也是建议自增id作为主键的根本原因

3、为什么要用索引

索引的目的是为了提高查询效率。如果没有索引就要a-z进行全表扫描。

4、索引的使用场景

4.1、主键自动建立唯一索引 Primary Key = Unique Key + Not Null

4.2、频繁作为查询条件的字段应该创建索引(银行系统的银行账号、电信系统的手机号)

4.3、查询中与其它表关联的字段,外键关系建立索引 

4.4、查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度

4.5、查询中统计或者分组字段

4.6、单值/组合索引的选择问题:在高并发下倾向创建组合索引    index(name,age,gender)
 

5、索引为什么要用B+树,为什么不能用二叉树、红黑树、B树?

介绍一款可以帮助理解数据结构的网站(很好用):Data Structure Visualization

5.1 二叉查找树

  1. 每个结点最多两个子树,分别称为左子树和右子树;
  2. 左子节点的值小于当前节点的值,右子节点的值大于当前节点值;
  3. 顶端的节点称为根节点,没有子节点的节点值称为叶子节点;

时间复杂度:平均 O ( log n ) 最坏情况下:O ( n ),会变成线性的二叉树

缺陷:

1.最坏情况下变成线性二叉树,时间复杂度变成O ( n )

2.在树查找时,每读取一次数据就会发生一次I/O,二叉树的深度越深,I/O的次数越多,而二叉树每个节点最多有两个孩子,若用二叉树作为索引,树的深度会很深,I/O性能消耗太大。

优化思考:把树的节点的数目增加,形成一个多叉树

5.2 红黑树(平衡二叉查找树)

  1. 每个节点只能是红色或黑色。
  2. 跟节点必须是黑色。
  3. 红色的节点,它的叶节点只能是黑色。
  4. 从任一节点到其叶子节点的所有路径都包含相同数目的黑色节点。

当数据插入时,红黑树通过旋转和变色来达到平衡。这样就弥补了二叉树退化成链表的尴尬

Q:为什么索引的数据结构不用红黑树?

因为当值依次递增插入时树的高度会变得特别高,效率会变得特别低。

时间复杂度为:O(log2N)

5.3 B树

  1. 一个节点可以有多个元素
  2. 叶节点具有相同的深度,叶节点的指针为空
  3. 所有索引元素不重复
  4. 节点中的数据索引从左到右递增排列

Q:为什么索引的数据结构不用B树?

虽然B树相对于红黑树,树的高度降低了,但是随着数据量的增多,树的高度还是会变得很高,效率会变得特别低。而且对范围查找也不方便。

5.4 B+树

  1. 非叶子节点不存储data,只存储索引(冗余),可以放多个索引。
  2. 叶子节点包含所有的索引字段
  3. 叶子节点用指针连接,提高区间访问性能(注意是单向指针。)

Q:为什么B+树比B树更适合做索引(MySQL)

  1. 磁盘读写代价低:非叶子节点仅用来索引(这样能存更多的关键字),数据都保存在叶子节点中,相对与B树能存放更多的关键字,磁盘读写代价低(树的深度低,读的关键字更多)
  2. B+树的查询效率更加稳定,是稳定的O ( log n )
  3. B+树更有利于对数据库的扫描,如进行范围查询,在普通查询时性能也更好

Q:为什么innodb表必须有主键?

因为innodb表的索引结构是B+树,而B+树是基于索引来存储数据的。所有的数据全部保存在B+树的叶子节点

Q:如果没有主键会怎么样?

innodb引擎会查找并选择第一个没有null值的列,作为主键索引。如果没有,则会使用隐藏列作为主键。

Q:为什么推荐使用整形自增主键而不用uuid?

优点:

节约空间
插入效率高(由于B+树遵循左小右大,所以自增插入数据总是在最右侧插入。而uuid则不一定,如果页16k已经写满了,那只能把页中的数据向后移,在空位中插入。频繁的移动分页会造成碎片,后续需要使用OPTIMIZE TABLE来进行碎片整理)
Q:为什么非主键索引结构叶子节点存储的是主键值?

非主键索引存储主键值,是为了当数据变动时,不需要修改各非主键索引的值,只需修改主键索引叶子结点的数据即可。减少了重复操作,即提高性能。
 

5.5 Hash

特点:类似于HashMap

查询效率极高(比B+树还高),但不能作为主流索引

缺点:

  1. 只能用于对等值的查询,不能实现对范围的查询,即:仅能满足“=",“IN",不能使用范围查询
  2. 因为Hash是通过hash算法计算出的hash值进行查找,因为计算过后的hash值的大小顺序不能保证和原数据一致(还可能会有hash冲突),所以不能使用范围查找
  3. 不能用于对数据的排序操作(也是因为hash算法的原因)
  4. 对与组合索引,不能使用部分索引查询
  5. 因为计算组合索引hash值时,是对整个组合索引一起做hash运算,计算结果不能拆分(即,abc组合索引,使用ab无法命中索引)
  6. 不能避免全表扫面
  7. 不稳定:遇到大量Hash值相等的情况,性能并不一定比B+树高(甚至有可能变成线性结构–链表)

总结:MySQL索引结构采用B+树,有以下4个原因:

 

1)、从磁盘I/O效率方面来看:B+树的非叶子节点不存储数据,所以树的每一层就能够存储更多的索引数量,也就是说,B+树在层高相同的情况下,比B树的存储数据量更多,间接会减少磁盘I/O的次数。

2)、从范围查询效率方面来看:在MySQL中,范围查询是一个比较常用的操作,而B+树的所有存储在叶子节点的数据使用了双向链表来关联,所以B+树在查询的时候只需查两个节点进行遍历就行,而B树需要获取所有节点,因此,B+树在范围查询上效率更高。

3)、从全表扫描方面来看:因为,B+树的叶子节点存储所有数据,所以B+树的全局扫描能力更强一些,因为它只需要扫描叶子节点。而B树需要遍历整个树。

4)、从自增ID方面来看:基于B+树的这样一种数据结构,如果采用自增的整型数据作为主键,还能更好的避免增加数据的时候,带来叶子节点分裂导致的大量运算的问题。

6、哪些情况索引会失效?

(1):条件是or,如果还想让or条件生效,给or每个字段加个索引

(2):like开头%

(3):如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不会使用索引

(4):where中索引列使用了函数或有运算

(5):对于多列索引,不是使用的第一部分,则不会生效

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

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

相关文章

hadoop生产调优之Hadoop-Yarn 生产经验(参数调优)

一、常用的调优参数 1&#xff09;调优参数列表 &#xff08;1&#xff09;Resourcemanager 相关 yarn.resourcemanager.scheduler.client.thread-count ResourceManager 处理调度器请求的线程数量 yarn.resourcemanager.scheduler.class 配置调度器&#xff08;2&#xff0…

js中ArrayBuffer和node中Buffer的关系和区别

ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。 它是一个字节数组&#xff0c;通常在其他语言中称为“byte array”。你不能直接操作 ArrayBuffer 中的内容&#xff1b;而是要通过类型化数组对象或 DataView 对象来操作&#xff0c;它们会将缓冲区中的数据…

C++、python、VS code插件安装与SSH使用

下载按照VS coda 官网&#xff1a;https://code.visualstudio.com 1.安装相关插件 1.中文插件&#xff08;可选&#xff09; MS-CEINTL.vscode-language-pack-zh-hans 2.C插件&#xff08;必选&#xff09; ms-vscode.cpptools 3.ssh 远程&#xff08;必选&#xff09; ms-vs…

数据结构——快排的三种实现方式

坚持看完&#xff0c;结尾有思维导图总结 这里写目录标题什么是快排&#xff1f;如何实现递归单次的排序要如何实现hore 的办法![在这里插入图片描述](https://img-blog.csdnimg.cn/40b2ac63f2424bd1828a45f8509ff116.gif#pic_center)坑位法双指针法总结什么是快排&#xff1f;…

线程池(一)

个人博客地址&#xff1a; http://xiaohe-blog.top/index.php/archives/14/ 文章目录1. 为什么要使用线程池2. Executor3. ThreadPoolExecutor3.1 七个参数3.2 任务队列3.3 拒绝策略4. 创建线程池5. Executors5.1 CachedThreadPool5.2 FixedThreadPool5.3 SingleThreadExecutor…

SAP UI5 应用里一些容器控件的介绍

sap.m.Shell 控件可用作应用程序的根元素。 它可以包含 App 或 SplitApp 控件。 Shell 为整个应用程序提供了一些总体功能&#xff0c;并负责在桌面浏览器平台上进行视觉适配&#xff0c;例如应用程序周围的框架。 sap.m.App: 该 App 继承自 sap.m.NavContainer 并因此提供其导…

VUEElement 学习笔记

1 VUE 1.1 示例 新建test_vue.jsp <% page contentType"text/html;charsetUTF-8" language"java" %> <html> <head><title>Title</title> </head> <body><div id"app"><input name"…

三、SpringBoot启动流程及自动化配置

一、Springboot启动流程 图一:Springboot项目的启动流程 首先,针对上图中自己不太明确的两个知识点,这里做如下总结: 1.Banner:参考这篇文章:SpringBoot之Banner介绍 - MarkLogZhu - 博客园 (cnblogs.com) ; 2.钩子方…

【Javassist】快速入门系列07 当检测到字段被访问时使用语句块替换访问

系列文章目录 01 在方法体的开头或结尾插入代码 02 使用Javassist实现方法执行时间统计 03 使用Javassist实现方法异常处理 04 使用Javassist更改整个方法体 05 当有指定方法调用时替换方法调用的内容 06 当有构造方法调用时替换方法调用的内容 07 当检测到字段被访问时使用语…

一个最基本的lLinux驱动开发框架和编译驱动方式

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、编写驱动文件1.相关头文件2.驱动入口 &出口3.申明完整代码二、编译驱动的方式三、编译驱动1. 和内核一起编译&#xff1a;2. 编译成驱动模块&#xff1a…

Kafka消息写入流程

Kafka消息写入流程 0,写入消息简要流程图 1,从示例开始 在Kafka中,Producer实例是线程安全的,通常一个Producer的进程只需要生成一个Producer实例. 这样比一个进程中生成多个Producer实例的效率反而会更高. 在Producer的配置中,可以配置Producer的每个batch的内存缓冲区的大小…

如何下载最新的NDVI数据?需要翻墙,安装MRT,如何处理下载的NDVI数据?

一、下载NDVI数据 参照网站&#xff1a; https://www.zhihu.com/question/48176218 1、先在网站https://modis.gsfc.nasa.gov/data/dataprod/mod13.php查看要下载的数据 其实没什么要看的&#xff0c;就看下面这个图就可以了&#xff0c;根据下图找到自己要下载的数据简称&am…

Python实现猎人猎物优化算法(HPO)优化支持向量机分类模型(SVC算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的优…

Hibernate-Validator的使用(一)

文章目录学习建议全部的约束注解关于NotEmpty和NotBlank的注意事项关于Size的注意事项约束注解可以放的位置JavaBeanValidator接口约束注解的继承性普通方法和构造方法入参和返回值ExecutableValidator 接口约束注解的继承性错误信息国际化显示定义message使用的消息key定义Val…

模仿现实生活中的通讯录(2)

距离第一篇已经过去很久&#xff0c;我之所以暂时放下通讯录&#xff0c;是因为学业颇多&#xff0c;无暇顾及。现在放假已经有一段时间了&#xff0c;脱离每天忙碌的生活后&#xff0c;我只想享受一下整日无事&#xff0c;浑浑噩噩过一天的感觉&#xff0c;只不过差点没收得住…

leetcode150/155. 逆波兰表达式求值、最小栈;剑指 Offer 31. 栈的压入、弹出序列

目录 题目链接与简介 题目一 1.算法思路 2.总结心得 3.可执行代码 题目二 1.算法思路 2.总结心得 3.可执行代码 题目三 1.算法思路 2.总结心得 3.可执行代码 题目链接与简介 1.逆波兰表达式求值 2.最小栈 3.剑指 Offer 31. 栈的压入、弹出序列 题目一 LeetCod…

软件测试 -- 进阶 8 软件测试流程和过程

盖天下之事&#xff0c;不难于立法&#xff0c;而难于法之必行&#xff1b;不难于听言&#xff0c;而难于言之必效。-- 明 张居正 释译&#xff1a;天下大事&#xff0c;困难的不在于要制定什么法律&#xff0c;而在于立了法就一定要执行&#xff1b;重要的不在于说什么&a…

【实时数仓】DWS层之地区主题表(FlinkSQL)、关键词主题表(FlinkSQL)

文章目录一 DWS层-地区主题表(FlinkSQL)1 分组开窗和聚合计算&#xff08;1&#xff09;分组窗口&#xff08;2&#xff09;选择分组窗口的开始和结束时间戳&#xff08;3&#xff09;系统内置函数&#xff08;4&#xff09;完整代码2 将动态表转换为流&#xff0c;写入ClickHo…

计算机基础(五):C语言的程序的处理过程

一段C语言程序 打开任何一个C语言的教程&#xff0c;首先自然是展示一段 Hello World 的程序&#xff0c;类似于下面这段&#xff1a; #include <stdio.h>int main() {/* 我的第一个 C 程序 */printf("Hello, World! \n");return 0; }运行上面这段程序也很简…

Qt中的数据库(简单使用)

在Qt中支持对数据库的操作 Qt中数据库的类有&#xff1a; 驱动层&#xff1a;为具体的数据库和SQL接口层之间提供底层的桥梁SQL层&#xff1a;提供对数据库的访问 QSqlDateBase类用来创建连接QSqlQuery可以使用SQL语句实现交互用户接口层&#xff1a;实现将数据库中的数据链接…