RDBMS| 青训营笔记

54 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天

这次来随便讲讲RDBMS吧(上班太缺时间了,所以讲的可能会有非常多的错误以及主观臆断,请选择性阅读,青豆:< )。

什么是RDBMS

从字面上就能拆开这个单词: R(relation)DB(database)M(manager)S(system),即关系数据库管理系统。我们使用的MySql、SQL Server、 Oracle,这些就是RDBMS, MongoDB是非关系的所以不在RDBMS里面。但是你把他简单的理解为数据库管理系统其实也没多大问题。

关系数据库被提出好像也有五十年了。第一个关系数据库是Oracle研发商用的,说到Oracle国内的很多银行都是用的Oracle的数据库,但好像初版的Oracle数据库开发的的相关人都走了,导致现在Oracle维护起来非常的麻烦,天天都是补丁。

在关系型数据库之前,是网状数据库和层次数据库。但是都有些无法克服的缺点。当然我并不是说关系型数据库就没有问题。和传统的数据库相比,关系型数据库已经是可以很好的表示现实世界中不同的关系模式了例如1:N,N:M等。

关系型数据库将实体和关系拆开成不同的表进行存储。这样虽然可以很好的解决模式问题,但是也不免会带来效率问题。例如你查询到的关系需要去指定的实体表中查询相应的实体,这就增加了查询次数。

RDBMS还需要在模型上加上一个十分重要的东西,也是我们最早接触的数据库内容:SQL。

SQL是一种结构化的查询语言,对人友好,但是对机器不友好。这个主要是方便人来对数据库进行操作。我们的输入的SQL会经过parse(解释器),optimizer(优化器)和executor(执行器),从而返回对应的结果。

SQL引擎

SQL是我们用来与数据库交互的语言。数据库作为一个十分重要的模块也使得SQL的使用十分普遍。

SELECT * FROM table1 WHICH a = 2

上面就是一条最常见的sql语句。

就像我们使用的其他编程语言一样,我们的sql也需要解释或者编译才能执行。

我们输入的sql首先会进入到Parser中,按照编译原理的方法,我们提取关键字生成AST语法树。这颗语法树就是我们的执行的流程。

随后AST进入到Optimizer中,对语法进行优化。或者说对流程进行优化,比如如果有连接操作,我们会选择小的表开始连接,这样的中间数据集要小一点而且速度要快一些。

optimizer中,我们有两类的优化措施,一种是基于规则的优化措施。我们上面讲的用小的表来连接就是一个规则优化,我们规定,从小的表开始。

而第二类优化是基于代价的优化。其实就是分析时间,选择最快的方式。就像我们在使用地图的时候,会计算一个路径的预计时间,这里代价刚好也是时间。但是这个代价究竟是什么,还是需要具体确定的。既可以是单一任务的执行时间,也可以是整体系统的吞吐量参数。

如果我们仅仅关注一个指令的执行,可能会造成整体系统的操作拥堵。在更高的层面上看我们并没有得到提升,那么这种基于代价的优化就失效了。所以具体如何进行优化还是需要具体问题具体分析,中间的细节还是很复杂的。

经过优化后,我们就生成了最终我们要执行的操作代码。随后代码会被送入到executor中执行。executor从数据引擎中获取数据,进行操作,最后将数据返回并写入日志中。

这里在executor中,我们有几种模型。分别是:火山模型、向量模型和编译模型。

火山模型吧,我觉得和火山也不像啊,不知道为什么叫做火山模型。其实就是个函数的调用栈。只不过这种模式每次一个结果都会返回一次,导致其效率较低。

随后就出现了向量模型,这个其实就是返回的结果不再是单一的结果而是一批(batch)结果,例如我们每次返回1000个结果,那么效率就比之前高了1000倍(笑)。

最后就是我们极致的速度,编译模型,你可理解为将executor要执行的操作直接编译为二进制代码,直接执行,这个是最快的。但是考虑到SQL的多变与需求的复杂性。我们没法对所有的sql都使用编译模型。不过可以对部分频率高的sql进行编译操作。

数据引擎

数据引擎是用来组织数据存储与数据流的。我们使用的数据库数据部分其实可以分为两部分,一个是内存部分一个硬盘部分。

内存和硬盘的存储速率差距十分大。如果所有的操作全部都直接与硬盘操作,效率将会十分低下。所以我们在内存中有一个缓冲池。我们的与数据库交互的数据,都会暂存在这块地方。直到日志写入到硬盘后,开始逐步的写入到硬盘中。

数据库一种最常见的数据保存形式是B+tree。每层的数据还是一个双向链表存储。这样的好处是可以进行范围的查找。因为B+树是有序的,如果我们遇到一个大小比较。当我们找到一个满足要求的数据后,就可以通过链表查询前后的数据了。提高了查询速度。

我们的index也可以是使用B+树。但是使用索引有个问题就是,如果这个索引不是主索引(数据不和索引放在一起),那么我们通过索引找到的数据实际上是一个主索引的指针或者值。我们需要使用这个值来重新搜索主索引才能拿到对应的数据。这个操作在Mysql中叫做回表。也是一个十分消耗时间的操作。SQL的优化这方面也是重点。

事务引擎

事务是为了满足ACID要求的:

  • Atomicity:InnoDB中通过undo日志实现了数据库的原子性,通过Undo Log,数据库可以回滚到事务开始的状态;

  • Isolation:通过Undo Log实现MVCC(多版本并发控制),降低读写冲突。

  • Durability:通过Redo Log(一种WAL实现方式)来保证事务在提交后一定能持久化到磁盘中。

  • Consistency:一致性本质上是一种业务层的限制。

A就是原子性,要么都做要么都不做。

I就是隔离性,我们的锁就出自这里。

D就是持久性,我们写入的数据不会丢失,这里是通过日志来完成的。

C就是一致性,不会出现非法的数据。

这一部分就留个读者自行了解吧。