[深度好文]10张图带你轻松理解关系型数据库系统的工作原理

news/2024/11/14 19:34:17/

[深度好文]10张图带你轻松理解关系型数据库系统的工作原理

原文(欢迎关注):https://mp.weixin.qq.com/s/CNCfWRpv8QlICGvZkLG4Jw

尽管数据库在我们应用程序中扮演着储存几乎所有状态的关键角色,但人们对其运行原理的了解通常仅停留在较为浅显的层面,而数据库的高效稳定运行又是大多数应用系统基础性的保障。

因此,在本篇文章中,在不深入讨论数据库特有的细节问题的前提下,我将全面介绍你应当理解的关于关系型数据库索引的相关内容。此外,我将简洁明了地探讨事务和隔离级别,以及它们如何影响你对具体事务的思考和理解。

关系型数据库

什么是索引

索引是一种帮助减少数据查询时间的数据结构。索引在实现这一目标时,需要付出存储、内存和保持更新(较慢的写入速度)的额外成本,这使得我们可以跳过检查每一行表的繁琐任务。

就像书后面的索引页一样,它可以帮助你找到正确的一页。

书后面的索引页

为什么需要索引

小量的数据是易于管理的(比如一个小班级的出勤表), 但是, 当数据规模变得更大时(比如一个大城市的出生登记), 事情就不那么容易了。之前能够很快执行的操作都开始变得缓慢。

想象一下,如果你需要在一页 A4 纸的名单上上找到某个信息,与需要在上千页的名单中找到它,你的查询策略会有何变化。

无论你想到的查询策略是什么,几乎总会有某个数据库在某个特定的时间点用到了和你相似的策略,因为随着它们的发展,他们需要收集和存储的数据会逐渐变得庞大,最终必将遇到上述的问题。

因此,我们需要索引来帮助我们尽可能快地获得我们需要的相关数据。

索引是如何工作的?

一般而言,索引越多读取性能越好,但这是以写性能的降低为代价的,因为你需要保持对索引的更新

其中一个方案是根据查询方式来维护数据存储逻辑。比如你需要通过姓名来查询某个名单,那就将名单按照姓名进行排序。但这个策略有许多问题需要考虑:

  1. 如果我有多种查询方式呢? 比如,既有用姓名查询也有用身份证查询。
  2. 如果有新数据的写入, 写入速度会受到多大的影响?
  3. 如何处理数据的更新呢?
  4. 所有的数据操作的复杂度是什么样的呢?

无论你的原始策略是什么,肯定都需要一种维护数据顺序的方式以便获取相关的无序数据。

如下表中的例子,几乎不需要什么时间,我们就可以通过扫描整个表将查询到我们想要的数据。

+─────+─────────+──────────────+
| id  | name    | city         |
+─────+─────────+──────────────+
| 1   | Mahdi   | Ottawa       |
| 2   | Elon    | Mars         |
| 3   | Jeff    | Orbit        |
| 4   | Klay    | Oakland      |
| 5   | Lebron  | Los Angeles  |
+─────+─────────+──────────────+

加入存储的数据规模无法全部存放到内存,或者需要很长的时间才能将数据从磁盘加载到内存呢?如下表中,数据分散在磁盘中,无法完全加载到内存。

+──────────+─────────+───────────────────+
| id       | name    | city              |
+──────────+─────────+───────────────────+
| 1        | Mahdi   | Ottawa            |
| 2        | Elon    | Mars              |
| 3        | Jeff    | Orbit             |
| 4        | Klay    | Oakland           |
| 5        | Lebron  | Los Angeles       |
| ...      | ...     | ...               |
| 1000000  | Steph   | San Francisco     |
| 1001000  | Linus   | Portland          |
+───────+─────────+──────────────────────+

大部分 R&D 立刻想到了,我们需要字典(hash表)以及一种可以不需要扫描磁盘直接定位到正在查询的指定行的手段。

索引叶子节点提供指定列到索引的映射,它能够存储符合条件的行所在的位置。

RowIDs indexes mapping to table data

这些索引叶子节点是索引列和相应行在磁盘上的位置之间的映射。它提供了一种通过索引列来快速获取指定行的方法。扫描索引的速度会更快,因为它是你要搜索的列的紧凑表示(更少的字节)。它为你节省了读取一堆块来寻找所需数据的时间,而且更便于缓存,进一步加快了整个过程的速度。

这些索引的叶子节点是统一大小的,我们在每个块中尽可能多地存储这些叶子节点。由于这种结构需要对数据进行排序(逻辑上,而不是磁盘上的物理排序),我们需要解决必须快速添加和删除数据的问题。通常我们用一个双向链表来解决这个问题。

这里的好处有两个:它允许我们向前和向后读取索引叶子节点,并在我们删除或添加新行时快速重建索引结构,因为我们只是在修改指针。

由于这些叶子节点在磁盘上并不是按顺序排列的,我们需要一种方法来获得正确的索引叶子节点。

平衡树(B-Tree)

B树 VS B+树

B树 VS B+树

B+树主要区别是,不在中间节点存储任何数据。所有的数据引用都链接到叶子节点上,这样可以更好地缓存树状结构(中间节点数据规模小更便于缓存索引信息)。

其次,B+树叶子节点是链接的,所以如果你需要做索引扫描,你可以简单的线性遍历,而不是向上和向下遍历整个树,从磁盘上加载更多的索引数据。

在关系型数据库中,B+树的结构如下图:

数据库中的B+树

什么是事务

事务是数据库操作的基本单位,它要么完全成功要么完全失败,不可能存在部分成功部分失败的情况。

数据不一致

在不同数据隔离级别中可能会出现一些数据不一致现象,了解这些现象对于调试你的系统以及了解你的系统能够容忍什么样的不一致是至关重要的。

不可重复读(Non-repeatable reads)

不可重复读

如上图所示,如果你在事务中的两次后续读取之间不能获得一致的数据视图,就会发生不可重复的读取。在特定的模式下,数据库的并发操作可能会出现你刚读的值被修改,导致不可重复的读取。

脏读(Dirty reads)

脏读

类似地,当你执行了一次读取,另一个事务更新了同一行,但没有提交工作,你执行了另一次读取,你可以访问未提交的(脏)值(这不是一个持久的状态变化,与数据库的状态不一致), 就会发生脏读取。

幻读(Phantom reads)

幻读

幻象读取是另一种已提交的数据不一致现象,他常发生在处理数据统计的场景。例如,你在一个特定的事务中两次计算客户的总数。在两次连续的读取之间,另一个客户注册或删除了他们的账户(已提交),如果你的数据库不支持这些事务的范围锁,这将导致你得到两个不同的值。

隔离级别

SQL标准的四种隔离级别

SQL标准定义了4个标准隔离级别,这些级别可以而且应该被全局配置(如果我们不能可靠地知道隔离级别,就会发生一些奇怪的问题)。

可重复读(REPEATABLE READ)

在这个隔离级别下,确保在一个事务中多次读取同一数据时,得到的结果是一致的。

这意味着事务在开始时会创建一个一致的快照,然后在事务结束之前,其他事务对数据的修改不会影响该事务的读取结果。

在可重复读级别下,解决了不可重复读的问题,但可能出现幻读问题。

串行化(SERIALIZABLE)

这是最高的隔离级别,它确保事务之间的并发执行就像是顺序执行一样。

在这个级别下,事务串行执行,避免了脏读、不可重复读和幻读的问题。

虽然序列化提供了最高的数据一致性,但也牺牲了并发性能,因为事务必须依次执行,不能并行处理。

读提交(READ COMMITTED)

在这个隔离级别下,一个事务只能读取到已经提交的数据。这意味着脏读的问题被解决了,因为事务只能看到其他事务已经提交的数据。

然而,在这个级别下,可能会出现不可重复读问题。

读未提交

在这个隔离级别下,一个事务可以读取到另一个事务尚未提交的数据。这意味着一个事务可能会读取到脏数据(未经提交的数据),即脏读。

这个级别提供了最低的隔离性,允许并发事务之间产生相互干扰。

本文翻译编辑自:
https://architecturenotes.co/things-you-should-know-about-databases/


http://www.ppmy.cn/news/75708.html

相关文章

渗透模拟环境配置和工具介绍-渗透测试模拟环境(0)

我们在 渗透攻防环境搭建与攻防知识体系思维导图 一文中有整体渗透环境设计和说明,但渗透环境攻击路径是什么、网络配置怎么配置,渗透环境的渗透工具是哪些、有什么作用并没有介绍,本篇将继续展开环境功能演示(环境配置步骤和验证相对较多),为模拟环境攻防系列打好基础。…

中原雄狮官网上线 | LTD物流服务行业案例分享

​一、公司介绍 中原雄狮崛起于2017年,彼时,全国货运行业存在许多不良行为,无赖货主和黑心货站恶意拖欠货车司机运费,而货车司机作为弱势群体却势单力薄无依无助的问题,为了让司机的血汗钱能颗粒归仓,中原雄…

实现图形算法API[软光栅渲染器,C++]

最近有点烦,发烧感冒了三天[事实上是俩天,第三天是因为摆得太舒服了索性多玩一天],啥都没学,打守望先锋也把把被虐...,想着今天来提起键盘把之前的东西都总结一下。 那么话归真题,首先我是仿造opengl来写的…

图片转字符图片工具类

├── cn.xsshome.imagetool //包名├── convert │ └── ImageToChar //图片转字符图片、文本方法 ├── slideverifycode │ └── SlideVerifyCodeGenerateUtil //滑块验证码工具类代…

GWAS分析中的GO和KEGG富集分析

上一次,我们介绍如何根据显著性snp,使用bedtools根据上下游距离,根据gff文件注释基因。 这一次,介绍一下如何根据注释的基因,进行富集分析,主要是看一下GWAS定位的基因有没有某一个趋势,也算是…

【JavaSE】Java基础语法(五):数组详解

文章目录 🍸1.1 数组介绍🍸1.2 数组的动态初始化1.2.1 什么是动态初始化1.2.2 动态初始化格式🍸1.3 数组元素访问1.3.1 什么是索引1.3.2 访问数组元素格式1.3.3 示例代码 🍸1.4 内存分配1.4.1 内存概述1.4.2 java中的内存分配 &am…

【数据库】事务与并发控制

文章目录 事务什么是事务事务的主要特征事务分类隐式事务显示事务事务与并发控制锁死锁事务 什么是事务 宏观上看,事务就是一次完整的操作过程;程序角度看,事务是用户自定义的数据操作系统,由多条命令组成,内部所有命令语句要被当成一个整体,要么全部被执行,要么全部不…

HACKABLE: III

文章目录 HACKABLE: III实战演练一、前期准备1、相关信息 二、信息收集1、端口扫描2、访问网站3、查看网站源码4、扫描目录5、访问网址6、查看并下载7、访问网站8、查看文件9、解密10、访问网站11、访问网站12、查看文件13、解密14、访问网站15、访问网站16、下载图片17、隐写1…