Mysql系列 -索引模型数据结构

索引就是排好序的数据结构,可以帮助我们快速的查找到数据,那么底层的数据到底是如何存储的呢?

为什么InnoDB 用的是B+tree 存储结构?

大家可以看看这个可视化的网站
数据结构和算法的可视化工具
在这里插入图片描述
可以看到数据结构里面有链表,二叉树,AVL,红黑树,Hash,B tree ,B+tree等等,可以点击进入每个数据结构的可视化页面,玩一玩,看看插入时数据是怎么样排序的

1.二叉查找树(Binary Search Trees)

二叉树的特点是左边节点比右边节点小,每个叶子节点下的子节点最多只能有2个,每次插入都会先比较根节点,小的往左边,大的往右边。
在这里插入图片描述

缺点
由于只能有2个叶子节点,所以数据量大的时候树的层级会非常高,而且当插入的数据都是有序的,如下图,就会造成斜树,这样就退化成有序链表了
在这里插入图片描述

2.平衡搜索二叉树(AVL trees)

解决了斜树的问题,每次插入是时候节点会进行旋转,左小右大,减少了树的高度,非叶子节点最多拥有2个叶子节点,同时树的左右2边层级 相差不会大于1;
在这里插入图片描述

右旋LL:当想左边节的左子节点点插入数据,例如插入10,8,6的时候,为了保持树的平衡,会把10节点进行右旋,试树能够平衡
在这里插入图片描述
左旋RR:当想右边节的右子节点点插入数据,例如插入10,12,14的时候,为了保持树的平衡,会把10节点进行左旋,试树能够平衡

在这里插入图片描述

缺点
虽然解决了斜树的问题,但是还是会造成树的层级太高,每个叶子节点只能有2个子节点,查询的时候会造成IO次数太多

3.红黑树(Red-Black Trees)

在这里插入图片描述

网上有大牛总结了个顺口溜:根节点必黑,新增是红色,只能黑连黑,不能红连红; 爸叔通红就变色,爸红叔黑就旋转,哪边黑往哪边转

缺点
红黑树的缺点是每个叶子节点只能有2个子节点,查询的时候会造成IO次数太多,同时树的层级会非常高

红黑树和AVL树的区别

  • 红黑树不是完全平衡,不会像AVL那样要求左右2边节点的 绝对值差不大于1,它只要求部分达到平衡,但是提出了为节点增加颜色,红黑是用非严格的平衡来换取增删节点时候旋转次数的降低,任何不平衡都会在三次旋转之内解决。
  • AVL是完全平衡,在增加或者删除节点的时候,旋转的次数比红黑树要多。左右2边节点的 绝对值差不大于1。由于是完全平衡,所有查询效率要比红黑树高
  • 复咋情况下,就是如有删除节点,树要回复平衡,红黑树的复衡效率更高,因为最多只需要旋转3次就能回复平衡,而AVL树可能会旋转多次,效率更低
  • 在实际运用中,如果搜索的次数远远大于插入和删除,那么选择AVL,因为查询效率更高,如果搜索,插入删除次数几乎差不多,应该选择红黑树,因为维护效率更高。

4.Hash

Hash实际上是散列函数,它可以帮助我们大幅提升检索数据的效率,这是因为 Hash 只需要一步就可以找到对应的取值,算法复杂度为 O(1)。Hash 算法是通过某种确定性的算法(比如 MD5、SHA1、SHA2、SHA3);

采用 Hash 进行检索效率非常高,例如查 id = 100的数据,基本上一次检索就可以找到数据,而 B+ 树需要自顶向下依次查找,多次访问节点才能找到数据,中间需要多次 I/O 操作,从效率来说 Hash 比 B+ 树更快。但是,hash 有很多缺点

缺点

  • Hash 索引不能进行范围查询,例如id > 100就无法匹配索引
  • Hash 索引不支持最左匹配原则,例如有联合索引 a_b_c_index,abc3个字段,Hash 索引在计算Hash 值的时候是将abc3个字段合并后再一起计算 Hash 值,不会针对每个索引单独计算 Hash 值。因此如果用到联合索引的一个或者几个索引时,联合索引无法匹配
  • Hash 索引不支持 ORDER BY 排序
  • 当数据量很大时,hash冲突的几率也会很是大,造成hash碰撞

5.B tree(多路平衡查找树)

上面讲到的树有个共同的缺点,就是每个叶子节点只能有2个子节点,这样的话都会造成树的层级太高,IO效率太低。

B-tree 利用了磁盘块的特性进行构建的树。每个磁盘块一个节点,每个节点包含了很关键字。把树的节点关键字增多后树的层级比原来的二叉树少了,这样就变成了N叉树,并且每个节点保存key和value和data,这样的存储方式的好处就是只要查询到对应数据的键值,就直接返回data,大大提高了查询效率,减少数据查找的次数和复杂度
在这里插入图片描述

缺点
这样的存储结构有个缺点,就是由于每个节点都保存了key-value-data,那么一旦这个data的数据量大的话,例如这个数据有1k,10k或者更多,那么一个磁盘块(默认16KB)就无法保存这么多节点了,因为空间是有限的,保存不了的话就会生成子节点,这样的话树的高度又增加了,磁盘IO又多了,于是B树进行优化,就有了B+树

6.B+tree

B+树和 B树最大的不同是非叶子节点只储存key和value信息,没有data,data 只保存在叶子节点上。这样做的好处是一个磁盘块可以存更多的节点,因为不需要存data了,树的高度就更矮了IO次数更低。

而且所有的叶子节点都是有序的双向链表,所有数据是按照顺序排列的,这样做的好处是范围查找,排序查找,分组查找的效率更高了,举个例子,例如查 23 < id < 52区间范围的数据,只需要找到23的这个数据,再通过有序链表,找到52,就可以快速的返回范围数据,减少了IO次数,提高查询效率
在这里插入图片描述

InnoDb的索引数据模型

在 InnoDB 中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表。又因为前面我们提到的,InnoDB 使用了 B+ 树索引模型,所以数据都是存储在 B+ 树中的。每一个索引在 InnoDB 里面对应一棵 B+ 树
从图中不难看出,根据叶子节点的内容,索引类型分为主键索引和非主键索引。主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index)。非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。

主键索引和非主键索引的查询区别

如果语句是 select * from T where ID=500,即主键查询方式,则只需要搜索 ID 这棵 B+ 树;
如果语句是 select * from T where k=5,即普通索引查询方式,则需要先搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程称为回表。也就是说,基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询。

索引维护

B+ 树为了维护索引有序性,在插入新值的时候需要做必要的维护;索引的每一页存放的是索引,如果新添加一个索引的话,这个索引素在的页内容满的话就需要新增一页,这时候会引起索引的移动到新的也上,影响性能
除了性能外,索引页分裂操作还影响数据页的利用率。原本放在一个页的数据,现在分到两个页中,整体空间利用率降低大约 50%。要求建表语句里一定要有自增主键。当然事无绝对,我们来分析一下哪些场景下应该使用自增主键,而哪些场景下不应该;也就是说,自增主键的插入数据模式,正符合了我们前面提到的递增插入的场景。每次插入一条新记录,都是追加操作,都不涉及到挪动其他记录,也不会触发叶子节点的分裂。而有业务逻辑的字段做主键,则往往不容易保证有序插入,这样写数据成本相对较高。除了考虑性能外,我们还可以从存储空间的角度来看。假设你的表中确实有一个唯一字段,比如字符串类型的身份证号,那应该用身份证号做主键,还是用自增字段做主键呢?由于每个非主键索引的叶子节点上都是主键的值。如果用身份证号做主键,那么每个二级索引的叶子节点占用约 20 个字节,而如果用整型做主键,则只要 4 个字节,如果是长整型(bigint)则是 8 个字节。显然,主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小;所以,从性能和存储空间方面考量,自增主键往往是更合理的选择。
有没有什么场景适合用业务字段直接做主键的呢?还是有的。比如,有些业务的场景需求是这样的:**只有一个索引;该索引必须是唯一索引。你一定看出来了,这就是典型的 KV 场景。**由于没有其他索引,所以也就不用考虑其他索引的叶子节点大小的问题。这时候我们就要优先考虑上一段提到的“尽量使用主键查询”原则,直接将这个索引设置为主键,可以避免每次查询需要搜索两棵树。

7.写在最后

总结了这么多,如果你还是不明白为什么要用B+tree做存储结构,那就再反复的学习吧

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

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

相关文章

Postman接口自动化测试之——批量参数化(参数文件)

Postman接口请求中的参数引用格式&#xff1a;{{参数名}}参数文件只适用于集合中。 创建参数文件 以记事本举例&#xff0c;也可以使用其他编辑器&#xff1b;第一行参数名&#xff0c;用半角逗号&#xff08;英文逗号&#xff09;隔开&#xff0c;第二行为参数值&#xff0c…

Linux -----------------------Shell 流程判断

什么是shell Shell是操作系统的用户界面&#xff0c;负责接收和解释用户的命令&#xff0c;并将这些命令转化为操作系统内部能够理解的指令&#xff0c;然后执行相应的操作。Shell还允许用户编写脚本&#xff0c;以自动化和批处理任务&#xff0c;从而提高效率。在Linux系统中&…

100G QSFP28 BIDI LR1光模块最新解决方案

上期文章我们有介绍到100G QSFP28 BIDI ER1 Lite光模块&#xff0c;本期内容我们将继续为大家介绍100G光模块系列的100G QSFP28 BIDI LR1光模块。这款产品同样也在易天ECOC光通讯展展出&#xff0c;下面跟着小易一起来看看吧&#xff01; 易天光通信的100G QSFP28 BIDI LR1单纤…

Redis中String类型的命令

目录 Redis中的内部编码 redis的数据结构和内部编码 Redis中的String类型 String类型的常见命令 set get mget mset String类型的计数命令 incr incrby decr incrbyfloat 其他命令 append getrange setrange strlen String类型的内部编码 Redis中的内部编码…

【源码】智能导诊系统,通过患者的主诉症状,自动匹配挂号科室和医生

随着计算机技术、网络技术、医院内网、智能终端的发展成熟&#xff0c;自动化、智能化就诊将是未来医院的发展模式。在目前综合性医疗机构&#xff0c;医院建设物庞大且复杂&#xff0c;接待就诊人员数量较大&#xff0c;医院诊疗科室众多&#xff0c;就诊人员容易迷失其中&…

Vue监听事件

一、问题场景 项目有个需求&#xff0c;在登录页面&#xff0c;输入好账号密码后&#xff0c;直接可以点击回车就能够登录&#xff0c;效果和点击登录按钮一样&#xff0c;登录页面源码如下 <template><body id"poster"><el-form class"login-…

linux 下 物理迁移 mysql 数据库 不能启动问题

1、授权问题 # chown -R 777 /app/db/mysql 2、/etc/my.cnf配置问题 [mysqld] basedir/app/db/mysql datadir/app/db/mysql/data socket/app/db/mysql/mysql.sock.lock innodb_buffer_pool_size128M innodb_force_recovery 1 symbolic-links0 [mysqld_safe] log-error/app/…

嵌入式linux常用的文件传输方式

做嵌入式就避免不了移植工作&#xff0c;所谓移植就是将交叉编译生成的可执行程序&#xff0c;库&#xff0c;配置文件等传输到开发板上进行工作。 常用传输方式有以下几种&#xff1a;1.串口传输 就是使用串口传输工具rz/sz; 该工具通过串口传输在SRT串口工具…

软文推广没效果?媒介盒子分享软文优化技巧

虽然软文推广能够为企业实现品牌增值&#xff0c;但也有许多企业在推广过程中犯错导致宣传没有效果&#xff0c;今天媒介盒子就来和大家聊聊企业在进行软文推广中的常见问题以及优化技巧。 问题1&#xff1a;内容生硬无法自然融入品牌信息 这也是企业在软文写作中较常出现的问…

win7中安装node14和vue

下载并安装低版本node 13 到官网去找早期历史版本的 nodejs 13 msi格式即可&#xff0c;并一键安装&#xff0c;我安装在了 D:\Program Files\nodejs 目录下 https://nodejs.org/download/release/v13.14.0/ 下载高版本node 14 下载高版本的node zip包 https://nodejs.org/…

生产环境docke问题排查

查看进程top查看具体的线程 top -H -p 8898如果cpu 过高&#xff0c;就是有问题的地方&#xff1b; 接下来根据docker查看具体的问题 查看dockers容器哪个内存、cpu占用过高 docker stats前言&#xff1a; 有java 启动容器&#xff1b;有jre包启动的容器。如下图 根据cpu很高…

【flink】Task 故障恢复详解以及各重启策略适用场景说明

文章目录 一. 重启策略种类&#xff08;Restart Strategies&#xff09;1. Fixed Delay Restart Strategy2. Failure Rate Restart Strategy3. Fallback Restart Strategy4. No Restart Strategy 二. 故障恢复策略&#xff08;Failover Strategies&#xff09;1. &#xff08;全…

【pdf密码】PDF没有密码,为什么不能编辑?

打开PDF文件的时候&#xff0c;没有提示带有密码&#xff0c;但是打开文件之后发现没有办法编辑PDF文件&#xff0c;这个是因为PDF文件设置了限制编辑&#xff0c;我们需要将限制取消才能够编辑文件。 那么&#xff0c;我们应该如何取消密码&#xff0c;编辑文件呢&#xff1f…

如何在校园跑腿系统小程序中构建稳健的订单处理与分配系统?

1. 数据库设计 首先&#xff0c;设计订单数据结构。使用数据库&#xff08;例如MySQL、MongoDB等&#xff09;&#xff0c;创建订单表以存储订单相关信息&#xff0c;包括订单ID、用户信息、交付地址、订单状态等。 CREATE TABLE orders (order_id INT AUTO_INCREMENT PRIMAR…

02【保姆级】-GO语言开发注意事项(特色重点)

02【保姆级】-GO语言开发注意事项&#xff08;特色重点&#xff09; 一、Go语言的特性1.1 第一个hello word&#xff08;详解&#xff09;1.2 开发编译。&#xff08;重要点 / 面试题&#xff09;1.3 开发注意事项1.4 GO语言的转义字符1.5 注释1.6 API 文档 之前我学过C、Java、…

Nginx代理转发请求POST变GET请求问题

&#x1f680; 注重版权&#xff0c;转载请注明原作者和原文链接 &#x1f96d; 作者&#xff1a;Yuan-Programmer &#x1f34e; 个人博客&#xff1a;https://boke.open-yuan.com &#x1f349; 已经替换了新的域名&#xff0c;总站叫做&#xff1a;OpenYuan开袁网&#xff0…

EASYX实现多物体运动

eg1:单个物体运动使用easyx实现单个小球的运动 #include <stdio.h> #include <easyx.h> #include <iostream> #include <math.h> #include <stdlib.h> #include <conio.h> #include <time.h> #define PI 3.14 #define NODE_WIDTH 4…

设计融合_ c#

单例模式 using System; namespace DesignIntegration{ public class TimeManager{ private static TimeManager _instance; private static readonly Object locker new Object(); private TimeManager() { } public static TimeManager…

手机app 爬虫

近期在做某个项目,涉及到需要对手机app的进行数据爬取。在上一篇博文中,讲述了以模拟机为例的配置操作流程,这里将以苹果手机为例进行描述。 下面将讲述具体配置步骤 1、安装 抓包软件 fiddler (Fiddler | Web Debugging Proxy and Troubleshooting Solutions) ​ 下载后…

【Java】AI+智慧工地云平台源码(SaaS模式)

伴随着科学技术的不断发展&#xff0c;信息化手段、移动技术、智能穿戴及工具在工程施工阶段的应用不断提升&#xff0c;智慧工地概念应运而生&#xff0c;庞大的建设规模催生着智慧工地的探索和研发。 一、带你认识智慧工地 伴随着技术的不断发展&#xff0c;信息化手段、移动…