MySQL数据存储原理一

2023-11-11

执行计划

  • id

    sql比较复杂的话,id列值会有好几个,它表示具体sql语句要执行的顺序

  • type

表示访问数据或进行查询的时候,所对应的类型是什么。效率优先级由低到高,all->index -> range -> index_ref -> cost -->system。all代表全表扫描 ,效率最低的一种方式,system效率是最高的。

如果sql语句里面有type=all,一定要进行sql优化的,尽可能的保证type类型的值在range以上。

执行计划的官网文档

https://dev.mysql.com/doc/refman/5.7/en/explain-output.html

点开type,可以看到每种类型的解释

all的效率是最低的。

  • key

    当前的sql语句在执行的时候索引列用的是哪个,有没有在使用索引

  • key_len

    索引长度

  • extra

    额外信息,比如using index、using index condition、using where、using filesort(用文件排序,涉及到文件的io,性能较差)

什么条件都不带的排序 怎么进行优化

大部分的排序都是在内存中进行的,比如冒泡、归并、快排、希尔排序、基数排序、堆排序。

如果数据量非常非常大的话,内存存不下怎么办?可以利用索引,

索引要看名字,不要看行数

使用索引排序,

使用临时文件排序。利用索引的效率更快一些。

如果是一个全乱序的数组,在进行查看的时候,需要把所有的数组加载到内存里面,然后再进行一个排序。

如果数据本身是有序的,直接从数据文件中把数据取出来。

利用了索引的有序性这个特点来进行相关的优化和调整,这就是执行计划带给我们的意义。

索引系统设计所需的基本理论知识

执行计划最关键最核心的点在于索引,索引加快数据的访问。

索引采用b+树数据结构。

数据存储在磁盘,读取磁盘数据,内存和磁盘数据进行交换。

  • 从硬件层面优化

IO (输入和输出) 是硬件层面解决问题,比如将机械磁盘换成固态磁盘(机械硬盘是一种传统的硬盘,它包括磁盘的转轴,磁头控制器,数据转换器和控制马达。而固态硬盘,就是由固态的电子储存晶片组成的硬碟)。

  • 软件层面优化方向

尽量减少读取次数,每次读取量尽量少。

考虑存储的数据是什么类型的数据(数据格式),比如书的目录,先找到目录名称对应的页面,直接翻到对应页看找到内容。

索引是由关键字和指针组成,存储是K-V格式的数据。用什么样的数据结构来进行存储这个数据?

比如hash表、树(二叉树、红黑树、avl树、btree、b+tree等),但不管什么样的数据,要保持K-V的数据格式。

查询出来的数据是一行一行的,而写到磁盘是一个个固定的文件。

一个文件假设1T的磁盘,没有1T的内存空间存储全量数据,保证数据在读取的时候要分块读取,比如每次读10M,切分成一个一个的单独块,分的次数多些或者需要读的时候再读,不需要读的时候就不读了。

操作系统基本概念

  • 局部性原理

    数据和程序都有聚集成群的倾向,叫空间局部性,在进行数据拼接的时候把某些具体类别的数据放到一起,比如相同特征的数据放在一起,不相同不放在一块;之前被访问过的数据有可能很快被下一次访问到,这个叫时间局部性。

  • 磁盘预读

    内存跟磁盘发生磁盘交互的时候 ,有一个基本的逻辑单位叫做页,页的大小跟操作系统相关,一般是4K或8K,在进行数据交互的时候数据大小是页的整数倍,比如某一页是4KB,读数据的时候可以是8K、16K、32K 、64K,必须是整数倍。分块的时候,每次读取大于4K或者 4K整数倍的数据,也没有固定块大小多少,是4K的整数倍就行了。

innodb存储引擎,每次读取16KB的数据 ,不管磁盘文件多大,每次就读取16KB。

借鉴了这些理论知识来进行索引系统的设计。

如何存储数据

K-V数据格式,K是索引的值,V代表当前整个行记录/数据。

把数据聚集成群的进行存放,需要选择合适的数据结构,一个是hash表,一个是树。

  • hash表

计算下当前key的hash位置,放入某一个格子,如果有元素就往上面追加,如果没有元素直接放入进去。

hash数据结构的问题

  • hash冲突

    需要优良的hash算法,否则会造成hash碰撞或hash冲突问题。比如0246有元素,1357没有元素,没有元素会浪费存储空间,导致数据散列不均匀。

  • 无序

    无序会导致无法进行范围查询,本身hash是散列的方式乱序放入。比如id>3 ,将会进行全表扫描, 效率极低。

  • 需要大量的内存空间

    在创建的时候,必须指定好长度,后面会进行扩容,但是对内存的消耗是比较大的。

mysql中是有hash索引的

https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_hash_index

对于memory这种存储引擎,是支持hash索引的。在内存里,就算挨个对比,效率依然很高,不在磁盘中,不会发生内存和磁盘之间的数据交换。

innodb支持自适应hash。

树是比较复杂的

RST(鲁棒序列树)和AVL(平衡二叉查找树)和红黑树都属于二叉树。每一个节点有且仅有两个分支,只不过在AVL和红黑树会有一个平衡的过程,保证左右子树空间存储的数据尽可能一致。AVL是严格意义上的平衡树,红黑树是非严格。

将二叉树作为数据结构,会有什么问题

每个节点有且仅有两个分支。左边是小于key的,右边是大于key的。如果想往当前结构里面插入更多的数据的话,就可能会导致当前这棵树变得无限深,太深的话,会导致io次数会变高,最根本的原因在于二叉有且仅有两个分支,但是它里面依然有借鉴的地方即有序,缺点在于二叉。

为了保证这棵树不变高,变成一个"矮胖子",变形为多叉排序树(无论三叉还是四叉...),保证每个节点上尽可能多的去存储数据。

https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

b树和b+树在进行数据插入的时候,有一个叫degree 度的, 表示每个节点最多可以存放多少个元素值。

每个节点里面只能放一个key值 ,多叉意味着有多个分支 (多个分支的话,一定要区分分支的范围)所以上面一定是多个值,有多个的范围。

如果degree=4 就说明每个节点中可以放4-1=3的数据量。

10个数据,分三层。整个b树里面没有重复数据。

怎么把这样数据映射到数据库表里面?

在检索一行记录的时候,有key值和value(整行记录),就意味着key值和整行元素变成一个集合放到节点里面,变成某一个节点的值。在这种情况下做了一个演变或者叫变形,

这是一个b树,在b树里面每一个磁盘块叫页,每个磁盘块默认16KB(这个大小可以自己去调整,默认是16KB)。在每个磁盘块里面,放了三个类型的数据,第一个类型指针,第二个类型是key值(索引列里面的数值),第三个类型是data整行的行记录。

b树的数据和key值放在一起,对于当前的三层的b树而言,如果要读取28这条记录的话,先拿到根节点,拿28和16做对比,大于16,小于34,则找到p2,通过p2找到磁盘3,在磁盘3上继续做判断,28大于25,小于31,找到p2指针,再通过磁盘3的p2指针找到磁盘8,进而找到key=28的数据。

在这整个遍历的过程中,读了多少数据或者读了多大的数据,每一块是16KB,读了3个磁盘块,16x3,一共读取了48kb的数据。

目前这样的一个数据结构,能存储的数据量有多少

一个表用这样三层数据结构来存储的话,这个表里面可以存储多少条数据。

假设一个data就代表一行记录,假设一行记录等于1kb,当前磁盘块里面最多可以存放15条记录。key和指针都是占空间的,为了方便计算,假设这些东西不占用空间,如果一个磁盘快存储16个数值的话,三层共16的三次方4096条记录,数据量很少。那如果想存储8000条怎么办,只能往下加一层,高度就变高了。为什么才存储了4000多条数据,是谁占用了大量的存储空间?

data 这里面要把分支变多,在整个基础之上,能不能让第一层和第二层不存数据 ,只放key值和指针。

在这个数据之上,就变成了b+树的数据结构。

b+树的特点:

  • 叶子节点有一个双向链表可以进行操作,

  • 有很多重复数据,第三层有所有数据(key和data),第一、第二层有部分key数据,属于重复数据。

  • 第一层和第二层不存储data数据,只有最下面的叶子节点存储数据

B+Tree是在BTree的基础之上做的一种优化,变化如下:

  • B+Tree每个节点可以包含更多的节点,这么做的原因,第一个是为了降低树的高度,第二个是将数据范围变为多个区间,区间越多,数据检索越快

  • 非叶子节点存储key,叶子节点存储key和数据

  • 叶子节点两两指针相互连接(符合磁盘的预读特性),顺序查询性能更高

  • 在B+Tree上有两头指针,一头指向根节点,另一头指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式结构,因此可以对B+Tree进行两种查询运算:一种是对主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

第一、二层少了data,叶子节点用一个双向链表把所有数据链接起来了

那当前b+能支持的数据存储量有多少?

数据总量没变,还是三层,还是读48K的数据,假设p1和20是一组,共同占用10个字节,第一个磁盘块可以存储多少个分支?16K等于16 X 1024个字节,为了好算,1024当1000来算,除以10即16 X 1000 / 10 =1600个分支,第二层也是1600个分支,第三层一个data为1kb即一个磁盘块存储16条数据,三层可以存储的数据规模是4000万,扩展了1万倍,所以3到4层的b+树,足以支撑千万级的数据量。

整体的块大小是不变的,key值发生了变化,如果key值+指针占100个字节,16x1000/100即160X160X16=40万零9600。

索引类型用int类型还是varchar类型

int 4个字节,varchar如果指定3个字节,在进行实际数值存储的时候,要看占用的字节数,一般情况下,你用varchar的情况肯定超过了10或超过4 ,但不排除其他情况,所以一般情况下用int。

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

MySQL数据存储原理一 的相关文章

  • Keytool 应用程序在哪里?

    我需要在android中使用mapview控件 但我似乎不明白如何运行keytool 是用eclipse安装的吗 我好像找不到下载链接 Thanks keytool http docs oracle com javase 7 docs te
  • HashMap不写入数据库

    我尝试在我的数据库中写入 但只写入发件人和消息 我不明白为什么会发生这种情况 我认为问题出在我使用 sendMessage 的地方 我认为问题是我没有什么可以做的读 写其他用户的主键 我在数据库中写入消息的活动 public class M
  • Java Try Catch Final 没有 Catch 的情况下会阻塞

    我正在审查一些新代码 该程序只有一个 try 和一个 finally 块 既然排除了 catch 块 那么如果 try 块遇到异常或任何可抛出的内容 它如何工作 它直接进入finally块吗 如果 try 块中的任何代码可以引发已检查异常
  • 未找到 MessageSource 的 ResourceBundle [消息]:找不到基本名称消息的包

    在 applicationContext xml 中 我定义了 MessageSource 如下所示
  • 如何从秘密字符串中制作 HMAC_SHA256 密钥以在 jose4j 中与 JWT 一起使用?

    我想生成 JWT 并使用 HMAC SHA256 对其进行签名 对于该任务我必须使用jose4j https bitbucket org b c jose4j wiki Home 我尝试根据秘密生成密钥 SecretKeySpec key
  • 在文本文件中搜索单词并返回其频率

    如何在包含单词文本的文本文件中搜索特定单词并返回其频率或出现次数 使用扫描仪 String text Question how to search for a particular word in a text file containin
  • 如何在 JSP 中导入类?

    我是一个完全的JSP初学者 我正在尝试使用java util List在 JSP 页面中 我需要做什么才能使用除以下类之外的类java lang 使用以下导入语句进行导入java util List 顺便说一句 要导入多个类 请使用以下格式
  • 无法在 Spring Boot 测试中模拟 persistenceContext

    我正在使用带有 Mockito 框架的 spring boot 测试来测试我的应用程序 存储库类 EntityManager 之一作为参考 我的班级如下所示 Repository Transactional Slf4j public cla
  • 如果使用的 JVM 是 x86 或 x64,则以不同的方式解决 Maven 依赖关系?

    我设置了一个 Maven 存储库来托管一些 dll 但我需要我的 Maven 项目根据使用的 JVM 是 x86 还是 x64 下载不同的 dll 例如 在运行 x86 版本 JVM 的计算机上 我需要从存储库下载 ABC dll 作为依赖
  • 内存一致性 - Java 中的happens-before关系[重复]

    这个问题在这里已经有答案了 在阅读有关内存一致性错误的 Java 文档时 我发现与创建 发生 之前 关系的两个操作相关的点 当语句调用时Thread start 每个具有 与该语句发生之前的关系也有一个 与 new 执行的每个语句之间发生的
  • 如何将 android.net.Uri 转换为 java.net.URL? [复制]

    这个问题在这里已经有答案了 有没有办法从Uri to URL 我正在使用的库需要这个 它only接受一个URL但我需要在我的设备上使用图像 如果该方案的Uri is http or https new URL uri toString 应该
  • 无法加载或查找主类,可以在命令行中使用,但不能在 IDE 中使用[重复]

    这个问题在这里已经有答案了 在将其标记为重复之前 请先听我说完 我正在尝试使用 gradle 导入一个 java 项目 功能齐全 适用于所有其他笔记本电脑 没有问题 我的项目 100 正常运行 适用于所有其他笔记本电脑 当我的笔记本电脑被重
  • 如何将 Jfreechart(饼图)添加到 netbeans 的面板中

    我正在使用 netbeans gui 编辑器 并且正在尝试添加一个本身位于内部框架中的 Jfreechart 并且这个内部框架我想将其添加到面板中 正如您在此图中看到的那样 抱歉 我无法直接发布图像 因为我新手 http www flick
  • Java 收集返回顶级项目的映射的嵌套流

    我有以下模型 class Item String name List
  • Cloudfoundry:如何组合两个运行时

    cloundfoundry 有没有办法结合两个运行时环境 我正在将 NodeJS 应用程序部署到 IBM Bluemix 现在 我还希望能够执行独立的 jar 文件 但应用程序失败 APP 0 bin sh 1 java not found
  • Spring Security OAuth2简单配置

    我有一个简单的项目 需要以下简单的配置 我有一个 密码 grant type 这意味着我可以提交用户名 密码 用户在登录表单中输入 并在成功时获得 access token 有了该 access token 我就可以请求 API 并获取用户
  • 如何在 Eclipse Java 动态 Web 项目中使用 .properties 文件?

    我正在 Eclipse 中开发动态 Web 项目 我创建了一个 properties 文件来存储数据库详细信息 用户名 密码等 我通过右键单击项目和 New gt File 添加它 我使用了Java util包Properties类 但它不
  • 将图像添加到自定义 AlertDialog

    我制作了一个 AlertDialog 让用户可以从我显示的 4 个选项中选择一个 前 3 个让他们在单击号码时直接拨打号码 第 4 个显示不同的视图 现在看起来是这样的 由于第四个选项的目的是不同的任务 我想让它看起来不同 因为用户可能会感
  • JVM:是否可以操作帧堆栈?

    假设我需要执行N同一线程中的任务 这些任务有时可能需要来自外部存储的一些值 我事先不知道哪个任务可能需要这样的值以及何时 获取速度要快得多M价值观是一次性的而不是相同的M值在M查询外部存储 注意我不能指望任务本身进行合作 它们只不过是 ja
  • 在android中跟踪FTP上传数据?

    我有一个运行 Android 的 FTP 系统 但我希望能够在上传时跟踪字节 这样我就可以在上传过程中更新进度条 安卓可以实现这个功能吗 现在 我正在使用org apache common net ftp我正在使用的代码如下 另外 我在 A

随机推荐