mysql深度剖析一(底层数据结构)

2023-10-31

衍变

二叉树
二叉查找树(容易形成链表)
二叉平衡树(可以自动调整高度,但层数容易过高)
多路平衡查找树即B树(层数控制了,但每个节点存有数据,导致每个磁盘页存不了多少索引,导致层数升高)
传统加强版多路平衡查找树即B+树(每个磁盘页可以存更多索引,进一步控制了层数,但最底层是单向链表)
innodb的B+树(叶子节点是双向链表,提升了范围查找与排序效率)

索引是啥

一种为了使查找方便而 排好序 的数据结构

查找需要几次磁盘io呢

查找索引为30的数据
在这里插入图片描述

1)先将B+数的根节点加载进内存中,发生了一次io;
2)30大于15,小于56,找到了30所在的磁盘页地址,再次加载进内存,发生了第二次io;
3)30大于20小于49,进一步找到了30所在磁盘页地址,再次加载进内存,发生了第三次io;
4)最后找到了索引为30所在地址及其数据;
通常根节点会常驻内存

B+树与页的关系

在这里插入图片描述

一页的大小是16384个字节,即16kb,可以通过执行show global status like ‘Innodb_page_size’来查看,此值可以改,但不推荐。为啥是16kb呢,试想若一页设定为非常大,即一页存放所有数据,只经过一次io就将数据加载进内存,对内存压力很大,而且一次io加载几百兆,甚至更多,也弄不了那么多,时间也长。

每一页存的是啥,可以存多少呢

每一页存的是索引值和指向下一层磁盘页的指针,称为一对,按照上边图,这里假设一对大小为8字节+6字节,14字节,那么16384除以14等于1170,即第一层可以存放1170对。第二层就有1170乘以1170对,第三层叶子节点根据不同的存储引擎可以存data,也可能存指针,所以按照一张表几十个字段,按照最大1Kb作为叶子节点大小,那么一页可以存16个数据,所以第三层可以存放1170乘以1170乘以16约为两千多万个数据;
一张表如果有上亿数据,一般会分库分表

为啥选择B+树而不是B树

在这里插入图片描述

每个节点带有数据,按照1Kb算,则一页可以存16个数据,那么要存2000万数据,需要多少层呢,以16为底,取2000万的对数,约为6,即16的6次方约为1600万;6层其实也不多,但也要6次磁盘io,时间已经翻倍了;

Myisam与innodb底层数据结构的区别

相同点:都是基于B+树,节点中的数据索引从左至右递增排列
三个不同点:非叶子节点有无数据,主键索引与非主键索引存储结构不同
Myisam中,.MYI文件存的是B+树,先在该树上找,而myisam叶子节点存放的是索引所在行的磁盘文件地址,再根据地址去.MYD文件中找到对应数据;索引与数据分开放,所以myisam的主键索引为非聚集索引;另外非主键索引也是这样存储;
Innodb中,.ibd文件存放的就是B+树,并且叶子节点是索引+所在行的数据,所以innodb的主键索引为聚集索引;非主键索引的叶子节点存储的是主键值;

非主键索引,二级索引,辅助索引是一个概念

非主键索引也是非聚集索引,需要回表,innodb存储引擎有且只有一个聚集索引
非主键索引的叶子节点存放的是该索引以及主键值,通常需要再次回到主键索引的B+树中,查找完整数据,此为回表。
二级索引比主键索引占用内存少,因为主键索引的叶子节点存放有完整数据,导致磁盘io每次传输数据更多;所以mysql系统会判断当select所查找的字段在二级索引和主键索引的叶子节点中均存在时,会优先选择二级索引去找即全索引扫描。若select所查找的字段在二级索引中只有一部分,则优先选择主键索引,这样可以避免回表,因为回表成本更高,而扫描主键索引的叶子节点,拿到所需数据,此即为全表扫描;但是若采用二级索引,则先拿到叶子节点中的主键,再根据主键去主键b+树中找到所需数据,相当于回表了,成本比全表扫描更高;
对于select * where xxx…,若xxx是非主键索引,线程此时无法扫描非主键索引的所有叶子节点而拿到数据,即无法走覆盖索引,也即无法走全索引扫描,此时mysql内部会进行比较,一是此时扫描主键索引树的所有叶子节点(全表扫描)拿到所有数据需要多长时间,二是此时根据二级索引叶子节点中的主键去主键索引树中回表查询需要多长时间,两个时间谁短就用谁;

覆盖索引

覆盖索引一般针对的是辅助索引,整个查询结果只通过辅助索引就能拿到结果,不需要通过辅助索引树找到主键,再通过主键去主键索引树里获取其它字段值;
即二级索引的叶子节点中的数据字段就覆盖了需要select的字段,不用回表就可以拿到。
二级索引树的叶子节点中只有二级索引字段和主键id,所以当select其他字段时,会回表;

为啥推荐innodb表必须建主键

不建也行,系统会找表中唯一键构建索引,如果无唯一键,则会用6字节的隐藏字段rowid,用它作为聚集索引来组织存放数据;所以自己先建好主键,系统会直接用主键构建B+树索引,岂不快哉

为啥推荐使用整型自增主键

使用自增主键,mysql底层在构建B+树过程中不断调整的次数要少,可以做个试验,针对两组数据,一组无序,一组有序,分别执行insert,构建B+树,构建网站是https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
数据顺序如下:
1 9 3 7 5 2 8 4 6
1 2 3 4 5 6 7 8 9
结果无序的一组,调整了四次,自增有序的一组调整了三次,当数据量大的时候,调整次数差别就明显了,所以调整次数越少,构建B+树效率越高。
使用整型易于比较,字母的话要转成ASCII码

联合索引也即复合索引

一张表不推荐建太多的单值索引,用几个字段组成的联合索引覆盖80%的sql语句;最左前缀原则的实现原理是先按从左到右的字段依次排好序,构建一个B+树,在这个基础上查找才有意义,比如(a,b,c)三个字段构建联合索引,如果只以b为条件,那么无法查,因为只有在a字段排好序的基础上,b字段才有序;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mysql深度剖析一(底层数据结构) 的相关文章

  • 不使用sequelize模型存储updatedAt

    当我将模型存储在 MySQL 数据库中时 它们是不可变的 因此 我可以在表中看到对createdAt列的需要 但我不需要冗余的updatedAt列 我可以将sequelize 配置为不存储updatedAt time 然后可以从表中删除该列
  • 使用 PHP 安全连接 MySQL 的最佳方法[重复]

    这个问题在这里已经有答案了 我想了解一下你们认为使用 PHP 连接到 MySQL 数据库的最安全方法 目前我正在做的方式是一个实用程序 PHP 文件 我将其包含在所有其他 PHP 文件的顶部 实用程序 PHP 文件是这样的 有什么建议么 建
  • MYSQL限制用户访问information_schema

    我有一个MySQL服务器 服务器版本 5 1 68 community MySQL客户端版本 5 0 51a 有没有办法限制所有用户对 information schema 的所有访问 发生的情况是 一些客户站点经常通过 SQL 注入遭到黑
  • 您可以使用 PDO 将占位符放入查询的选择部分吗?

    我打算使用 PDOprepare and execute 防止SQL注入攻击的机制 通常 SQL 中的占位符位于条件部分 例如select name age from members where age gt and gender f 但是
  • Update 查询中的 MySQL 子查询 select 语句

    我有 2 个表 tbl taxclasses tbl taxclasses regions 这是一对多关系 其中主记录 ID 是classid 我在第一个表中有一个名为regionscount 因此 我在表 1 中创建一个税类 然后在表 2
  • 如何左连接或内连接表本身

    例如 我将这些数据存储在表中 id name parent parent id 1 add self 100 2 manage null 100 3 add 10 200 4 manage null 200 5 add 20 300 6 m
  • 禁止 MySQL/MariaDB 中的存储过程使用 NULL 参数

    我可以指定表列不为空 但如何使存储过程或函数仅与非空参数兼容 在参数名称后添加 NOT NULL 不起作用 您需要自己验证传递的参数值 如果您使用 MySQL 5 5 及更高版本 您可以使用SIGNAL https dev mysql co
  • 私人消息系统。列出每个对话的最后一条消息

    可以说这是数据库结构 SELECT FROM pms where id to 1 or id from 1 这将返回他已接收或发送的所有消息 那么我如何检索最后一条消息each用户1可能进行的对话 PD 当两个用户之间存在一条或多条消息时
  • 将多个文件上传到服务器并

    我的第一篇文章所以要温柔 我尝试过搜索此内容 并且有很多类似的帖子 但我似乎找不到任何与我的问题完全相似的内容 而且我已经在这个问题上花了几个小时了 我正在用 PHP 5 3 和 MySQL 构建一个系统 部分功能是要求用户根据之前的一些选
  • 需要使用同一数据库中另一表的数据填充一个表

    我正在尝试使用 mysql 从另一个表填充一个表 第一个表是用户 第二个表是技术人员 用户包含 用户ID 姓氏 名字 登录ID 密码 访问级别 技术人员包含 techID tech surname tech firstname tech l
  • SQL:获取每组中的第N项

    我有一个这样的用户表 user id community id registration date 1 1 2008 01 01 2 1 2008 05 01 3 2 2008 01 28 4 2 2008 07 22 5 3 2008 0
  • 如何连接mysql表

    我有一张这样的旧桌子 user gt id name address comments 现在我必须创建一个 别名 表 以允许某些用户出于某种原因拥有别名 我创建了一个新表 user alias 如下所示 user alias gt name
  • 从 PHP PDO 执行时 MySQL 提交是否同步?

    使用 MySQL 的 PHP PDO 接口 假设我有以下代码来结束事务 假设它已正确开始 pdo gt query commit 当函数返回时 对日志的写入是否已刷新 也就是说 事务是否已提交 或者我只是提出了提交请求 假设我没有设置任何延
  • System TZ 和 DB TZ 之间的时区感知差异?

    我目前正在将数据库从本地 MySQL 主机迁移到 RDS 中的 Aurora 使用以下命令检查两个系统上的时区设置 SELECT system time zone global time zone session time zone NOW
  • MYSQL通过两个键内连接两个表

    我正在执行查询以返回存储在 sb carts 表中的所有用户购物车 存储在 sb carts 中的产品信息通过两个键 Product sku 和 school id 引用 它需要参考两者来返回具有独特库存水平等的独特产品 当我执行以下查询时
  • 限制检索的行数 MySql、Laravel

    问题 我的问题是使用 Mysql 或 Laravel 通过查询返回的行数是否有限制 首先 我使用 Laravel 5 2 我试图从日志表中检索数据 该表最近已超过 10k 行 现在从那时起 或大约那个时候 用于检索数据的常用 Laravel
  • 命令“python setup.py Egg_info”在 /tmp/pip-install-fs0wmmw4/mysqlclient/ 中失败,错误代码为 1

    当我在 Ubuntu 16 04 中输入以下命令时 pip install mysqlclient 我收到以下错误 enter code here Collecting mysqlclient Downloading https files
  • 无法从 Windows GUI 工具连接到远程 Linux 服务器上的 MySql 数据库

    我已经在 Amazon EC2 上的 Linux 服务器上设置了 mysql 数据库 这在本地效果很好 我可以登录 linux 盒子并管理 mysql 数据库 我正在尝试将本地 GUI 客户端连接到远程 mysql 但连接失败 我更新了 e
  • MySQL Workbench(版本 6.0.8)SSH 身份验证问题

    我正在尝试通过 SSH 通过计算机 Y 连接到主机 X 上的 MySQL 服务器 相同的设置 但 MySQL 工作台的版本较旧 适用于我的另一个机器 CentOS 6 3 但是 相同的设置在我的 CentOS 6 5 上不起作用 我尝试使用
  • MySQL空间几何验证wkt

    在 MySQL mysql gt select astext geomfromtext polygon astext geomfromtext polygon NULL 1 row in set 0 00 sec 但对于较新的 MySQL

随机推荐

  • gulp4.0入门, 看这一篇就够了

    前言 之前我们讲了gulp3 0 这篇引入gulp4 0 4 0相比3 0有一些改变的地方 gulp3 0压缩顺序默认是顺序执行的 4 0引入压缩并行的处理方式 gulp series 4 0 依赖顺序执行 gulp parallel 4
  • C# ASP.NET 连接MySQL 如何先进行多条件查询,然后进行数据库插入操作

    数据库内有很多字段 但是2个字段 id mac id 中的任何一个都不能在数据库的记录中重复 WEB网页上有n个TEXTBOX控件 用于输入数据库字段的值 其中 textbox1输入id字段值 textbox3输入mac id字段的值 插入
  • Python爬虫:设置Cookie解决网站拦截并爬取蚂蚁短租

    我们在编写Python爬虫时 有时会遇到网站拒绝访问等反爬手段 比如这么我们想爬取蚂蚁短租数据 它则会提示 当前访问疑似黑客攻击 已被网站管理员设置为拦截 提示 如下图所示 此时我们需要采用设置Cookie来进行爬取 下面我们进行详细介绍
  • VTM1.0代码阅读:compressCtu函数

    compressCtu函数是对一个ctu进行编码的函数 入口参数cs是pictrue的cs 这个cs里面存储当前帧的所有已编码过CTU的cu pu tu等信息 area为当前要编译ctu的区域 ctuRsAddr为当前ctu的rs扫描地址
  • 【笔记-node】《imooc-nodejs入门到企业web开发中的应用》

    目录 课程名 备注 入门必学 nodejs入门到企业web开发中的应用 框架与工具 node js koa2 mysql打造前后端分离精品项目 旧岛 项目实战 20190317 20200720 imooc nodejs入门到企业web开发
  • DTO/VO/Entity等数据类型转换

    DTO VO Entity等数据类型转换 在web开发中 前端传递数据给后端时采用DTO类型 而存入数据库时则采用entity类型 这样的操作存在类型转换 如果我们一个一个的设值也就太麻烦了 我们可以采用spring提供的jar包来解决这样
  • 计算机 创新方法举例,列举列举五种创新的方法并加以举例说明

    一 简化模式 在研发新产品时 我们总会不自觉的想要在产品上增加新的特色或功能 导致产品使用起来越发复杂 这样的画蛇添足对产品来说是一种负担 我们要运用简化模式 主要是将产品中多余的属性移除 再增加新功能 例如 手机从键盘按键模式变成触屏的虚
  • mybatisPlus update更新部分字段

    第一种方式 其中 lambdaUpdateWrapper set 表示要更新的字段值 eq 则表示 WHERE 条件 public void updateEntity LambdaUpdateWrapper
  • 人工智能AI生成的艺术:从文本到图像、视频、3D建模

    继去年火遍全网的虚拟人之后 AI绘画又成了今年热议的科技话题 AI绘画就是 以文生图 打通了文字和图像的隔阂 只要输入一段文字描述 AI 就可以把用户脑海中想象的画面呈现出来 这是一种文字转图像 Text to image 特性的崭新交互方
  • 基于SpringBoot的在线教育平台系统

    基于SpringBoot Vue的线教育平台系统 前后端分离 开发语言 Java 数据库 MySQL 技术 SpringBoot Vue Mybaits Plus ELementUI 工具 IDEA Ecilpse Navicat Mave
  • 【专题5: 硬件设计】 之 【69.开关电源 之 如何计算buck电路占空比和电感的计算】

    嵌入式工程师成长之路 系列文章 总目录 系列文章总目录 希望本是无所谓有 无所谓无的 这正如脚下的路 其实地上本没有路 走的人多了 也便成了路 原创不易 文章会持续更新 欢迎微信扫码关注公众号 承接 小程序 嵌入式 PC端项目开发 联系作者
  • Apache Kafka Connect JNDI注入漏洞复现(CVE-2023-25194)

    1 产品简介 Kafka Connect是一种用于在Apache Kafka和其他系统之间可扩展且可靠地流式传输数据的工具 它使快速定义将大量数据移入和移出Kafka的连接器变得简单 Kafka Connect可以摄取整个数据库或从所有应用
  • STM32+SG90舵机详解(详细)

    上一次使用舵机只是草草了解 只大概知道是pwm控制的 这次又使用到了舵机 本以为复制上次代码就可以调试成功 没想到却弄了很久 我使用的是STM32f103c8t6 用的是定时器4 这个f1板子的定时器各个通道io口如下图所示 在开始之前我们
  • git push -u origin master

    1 错误描述 出错场景描述 github上创建远程仓库的时候选择添加README md文件 git bash连接远程库 然后执行push操作 出现下面的问题 git push u origin master To github com XX
  • Linux 下存放ssh信息的文件位置

    vi root ssh known hosts root prme stg dhcp1649 StorageJavaAuto cat root ssh known hosts prme stg188 eng vmware com 10 11
  • axure创建网页

    最近发现一个好玩的东西 就是axure了 学习操作了下 弄出了一个简单的搜狗页面还有登录界面 该有的交互也弄了些 感觉挺好玩的 也扒拉下生成了html 好好看看 代码可能有点长 你忍一下qwq
  • Ubuntu小技巧19--Kibana安装方法

    Ubuntu小技巧19 Kibana安装方法 Kibana 是一款开源的数据分析和可视化平台 它是 Elastic Stack 成员之一 设计用于和 Elasticsearch 协作 可以使用 Kibana 对 Elasticsearch
  • c++pointer踩坑记录 (std::move, shared_ptr)

    要实现的需求 拿到一个指向数据的void 指针 用这个指针替换旧对象数据 要求 不额外申请内存 我在这过程中搜过的问题 看的知识点 how to use enum in c use std move to pointer std vecto
  • ElasticSearch中字符串类型(Text和keyword)的选择

    ElasticSearch 5 0以后 字符串类型有重大变更 移除了string类型 string字段被拆分成两种新的数据类型 text和keyword text 会分词 然后进行索引 用于全文搜索 支持模糊 精确查询 不支持聚合 keyw
  • mysql深度剖析一(底层数据结构)

    衍变 二叉树 二叉查找树 容易形成链表 二叉平衡树 可以自动调整高度 但层数容易过高 多路平衡查找树即B树 层数控制了 但每个节点存有数据 导致每个磁盘页存不了多少索引 导致层数升高 传统加强版多路平衡查找树即B 树 每个磁盘页可以存更多索