我眼中的 系统数据库
MySQL 数据库系统
MongoDB 我没找到合适的图片来说明,有时间我自己画一个贴上来
硬盘 & 内存
内存写入到硬盘上面的时候是分为几个单元,可以称之为事务,
其中几个操作分为一个单元,然后写入到硬盘里面,但是当正在写入到一个单元里面的时候,突然断了,这时候数据也就是丢失了,所以 需要一个记录写入单元时候的过程,这个时候就需要日志了,用来记录每个单元操作的过程,
当然还有另外一个办法就是操作在内存里面,为了防止突然宕机导致数据的同步不一致性,可以考虑开启日志,把所有的记录都存在日志里面,这样会有一个缺点就是,宕机的时候我们需要恢复日志里面所有的内容,然而日志里面的信息存在硬盘里面,这样如果要恢复日志,就需要把硬盘里面的信息计算加入到内存里面解析(这个时候会 加大 磁盘IO )所以效率并不是很好
比如说我要把一个苹果换成梨,其中的过程我们都是不关心的,只要能把苹果换成梨, 苹果 - 哈密瓜 - 柿子 - 梨 但是当换成哈密瓜的时候被旁边的一个进程调走了,这个时候有人来找梨,于是 查找的人就去找有没有梨,发现苹果还没有换成梨,在途中负责别的进程了,于是就去那个进程找苹果,这个时候就需要告诉找梨的人等着,这就是所谓的锁!
其中这两个进程就是不同的事务
InnoDB在运行过程中,会在可能的情况下使用异步磁盘I/O,主要通过创建多个线程来处理I/O操作,与此同时允许其他数据库操作,尽可能降低I/O操作和优化磁盘文件的组织(如,延迟某些I/O操作直到数据库空闲时,或者为了保证数据一致性,在数据库重启后执行某些恢复操作)。
分类(索引)
例子说: 图书馆的书籍管理,比如说我要一本文学的书,这样我们可以直接去文学类书籍的书架上面去找我们要找的书籍,但是假如我们的图书馆一遭乱(不分种类什么的,直接全推到图书馆),这样我么存(写)的时候是简单了,但是当我们查询(读)的时候就麻烦了,我们需要几乎全部扫描一遍,由于几乎所有的系统都是读大于写的,所以这样在效率上面就下降了很多,为了解决这个问题就出现了结构和索引
索引
索引的目的就是提高查询(读)的效率,就比如说我们在字典中查询 name 这个单词,我们肯定需要定位到n字母,然后再找到剩下的字母。所谓的索引就是 通过不断的缩小想要获得数据的范围来筛选出最终想要的结果
磁盘IO与预读
磁盘读取数据靠的是机械运动,每次读取数据花费的时间可以分为寻道时间、旋转延迟、传输时间三个部分,寻道时间指的是磁臂移动到指定磁道所需要的时间,主流磁盘一般在5ms以下;旋转延迟就是我们经常听说的磁盘转速,比如一个磁盘7200转,表示每分钟能转7200次,也就是说1秒钟能转120次,旋转延迟就是1/120/2 = 4.17ms;传输时间指的是从磁盘读出或将数据写入磁盘的时间,一般在零点几毫秒,相对于前两个时间可以忽略不计。那么访问一次磁盘的时间,即一次磁盘IO的时间约等于5+4.17 = 9ms左右,听起来还挺不错的,但要知道一台500 -MIPS的机器每秒可以执行5亿条指令,因为指令依靠的是电的性质,换句话说执行一次IO的时间可以执行40万条指令,数据库动辄十万百万乃至千万级数据,每次9毫秒的时间,显然是个灾难。
MySQL 目前提供下面4种索引:
- B+Tree 索引:最常见的索引类型,大部分引擎都支持B+树索引。
- Hash 索引:只有Memory引擎支持,使用场景简单。
- R-Tree 索引(空间索引):空间索引是MyISAM的一种特殊索引类型,主要用于地理空间数据类型。
- Full-text (全文索引):全文索引也是MyISAM的一种特殊索引类型,主要用于全文索引,InnoDB也从MYSQL5.6版本提供对全文索引的支持。
MongoDB 支持多种类型的索引 包括单字段索引、复合索引、多key索引、文本索引地理空间索引等,但是每种类型的索引在不同的使用场合效果会不同
SQL 的编写 & 执行
编写
编写的过程不过就是:
- 了解业务
- 构建数据
- 添加构建条件
- 添加构建笛卡尔积
而实际的业务应该体现在 select
什么数据
where
单条筛选条件group
组合筛选条件
数据的处理本质是计算,减轻程序计算压力,同时也加大了数据库计算压力
count(1) 比count 某一列甚至是索引都速度快为什么????
因为 count(1)
是只把1加载了 而 count(column)
需要列扫描所有的值,需要把值加载到内存里面读出来,所以就算是索引效率也比 count(1)差
执行
语法解析
传入一个SQL ,通过关键字将SQL语句进行解析,然后SQL解析器,MySQL解析器将使用MySQL语法规则验证和解析查询
查询优化器
优化器在查询树中遍历每个关系,确定关系是否是常量表,为每个关系查找可用的索引,运用关系 代数原理和启发式规则进行逻辑上的查询优化(如消除子查询,消除外连接等)。 然后对每个连接的表进行排序,再求解多表连接最优路径,对于每个关系尽量利用索引计算其 代价,找出代价最小的路径后保存到JOIN类的best_positions。
执行器
把查询执行计划传到执行器进行执行。