一个小型数据库的核心组件

如果想要了解存储,我比较推荐的方式还是从了解数据库开始。从目前来看,数据库发展了这么多年,各种理论相对的比较完善,面对各种应用场景,其核心处理模式也已经非常的成熟了,在新的海量数据的时代,人们只是对扩展性提出了更高的要求,而对数据存储的其他方面却仍然希望能保持之前的水平。

 

而从目前实际的发展来看,基本上目前发展的核心思路并没有绕开人们在数据库理论领域内所积累的那些关键的特性。因此,如果你希望能够快速的在海量数据的在线处理领域内积累知识,从传统数据库领域入手是绝对不会错的。

 

下面,就让我们对数据库做个简单的解刨,看看数据库里面有哪些核心的组件吧。

 

映射(Map):
首先就需要有能够存储数据并提供查询的结构,这个结构,在java里面就是Map。 C里面也是Map.他的核心作用就是,建立一种key与value的映射关系,当给定某个key的时候,他能够返回这个key所对应的value给用户。这是用户在进行查询时的主要数据结构。

 

 

预写式日志(write-ahead logging,WAL):
就是个队列,记录了你每一次写的操作。自然而然的,因为你的每次写操作都被记录下来了,所以就算计算机断电了,只要这个日志没有损坏,计算机重启后按照这个log ,重放在断电时的那些写操作,就可以保证你的数据不丢。
这里,一定会有人问:既然我数据都存储在k-v表里了,明显就不会丢失了。为什么还要有这个log呢?这其实就是一个计算机的本质性问题了,别看现代计算机运算速度这么快,他终归也只是个“图灵机”实现,或者更具象化一点,就是一台打字机,一次只能打一个字母,那么可能会有人问了,如果我要用几个字母来表示同一个意思,应该怎么做呢? 在英语中,最简单的方式就是在词组和词组之间增加空格。 比如write ahead logging. 就是三个由字母组成的单词。在计算机里,也有类似的问题,用户的一次写入操作,可能对应计算机内的多步操作,如何能够保证这多次的操作要么全部成功,要么全部失败呢? WAL就是个解决的方法,他利用的是操作系统里的一个原子操作fsync(). 该操作的作用是将一小段数据写入到磁盘,从而保证数据不会丢失。
我们来看一下整体的操作思路: 记录用户的写入操作(insert,update,delete)-> 进行内部多次key-value映射的构建,包括主数据,辅助索引数据等-> 标记该用户操作完成。

 

触发器(trigger)
一个不难理解的概念,当发生insert , update , delete等操作的时候,可能会有一些需求需要依托这些操作而被触发执行其他的操作。比如每一行针对表A的更新,都会引发B表内的更新。那么 这个“引发”的过程,就是触发器。在一些其他的语言里面,这也被叫做callback,IFTTT,Listener等。 但核心概念都一样,被动的因为某个事件而触发一段代码逻辑的运行。
在一些数据库的实现中,甚至二级索引的更新也是使用触发器来完成的哦:)
在数据库内,触发器全部是同步实现的,也就是说,只有当数据写入的操作,以及触发器的操作全部都执行完成后,才会返回用户执行成功。

 

锁(lock)
锁的主要目标是允许线程圈定一批资源,并规定该资源只允许发出圈定请求的那个线程进行访问,而其他线程则必须等待。
这个概念产生的主要原因其实还是与计算机是图灵机有关。。本来计算机就是台图灵机,一个时钟周期内只能打一个字母,但这样他就很难同时做好几件事情,比如听着歌写代码,这件事其实从计算机硬件来说是做不到的,他只能模拟,利用时分复用的方式,把cpu的运算分解成小片,每个线程都只占用一小段时间,从而能够做到同一时间做好几件事。但是,想一想,如果我们希望一个人A用打字机打i am god. 而希望另外一个人B用同一台打字机打 pig is money. 开始,时间片分配给A,他打印了i am后,A被cpu换出,B被换入,打印了pig 后被其他人换出, 那么我们自然就发现。。数据就变成了。。。 那么锁的作用就是保证一个逻辑的原子操作没有完结的时候,这张打印纸只属于A,其他人不能对其进行访问或进行修改。
明白了原理,来简单看看实现,锁主要是由排他锁(写锁)和共享锁(读锁)构成,在数据库的锁实现中,有很多针对共享锁和排他锁相互组合的细节性描述,但其核心的问题却永远没变:
1) 尽可能的减少同一时间内被阻塞的线程数,从而提升并行度。
2) 尽可能的避免死锁
可以说数据库实现的是好是坏,关键就看着锁的优化好不好,这在分布式场景或者在单机内都是最重要的一个机制。

 

执行优化器
这是关系数据库得名的原因,主要的作用是将关系查询转换成key-value 查询,输入是sql的抽象语法树(ast),输出则是执行计划,就是各位在数据库命令行打explain sql时候出来的那些东西。
理解上很简单,但实际上实现起来却是最为复杂的,在上个世纪,大部分的执行优化器使用rule based optimizer,也就是基于规则的优化,但在现代数据库实现中,大部分的优化器都采取了cost based optimizer了,他们之间最大的不同,就是cbo更多的考虑了数据实际的区分度情况,从而能更简单准确的从。多个可选的索引中选择一个正确的索引。

 

sql解析器
作用很简单,把用户输入的sql转化为计算机可以理解的抽象语法树(不懂就去看编译原理:)

 

好了,基本组件儿介绍完毕,下面我们利用这些核心组件来尝试拼装一些外围的概念。

 

第一个概念是:存储过程。

我第一次接触数据库的时候,对存储过程比较不理解。认为数据库么,使用关系模型就足够了啊,为什么还要支持一种类似编程语言的东西来额外的增加系统的复杂度呢?而且在当时,有大量的高级程序员在介绍他们的经验的时候都会分享说:尽可能不使用存储过程,那玩意儿非常不容易维护,也会增加非常多的使用成本,应该把所有业务逻辑放在客户端。那么我自然就有个疑问,既然这些事情客户端都能做,那么还要存储过程干什么?可能第一次接触数据库的人也会有我之前的困惑吧。。。呵呵,所以既然我已经能解答这个问题,在这里自然而然的也要尝试给有相同问题的人解惑。

 

存储过程其实不是个复杂的概念,他的核心目标就是让数据库端能够运行逻辑代码(判断,循环..etc),甚至在oracle,存储过程可以做任何事。 我们排除oracle希望用户只用数据库来完成一切功能的阴谋论,来看看事情的本源是什么?或者说,有什么事情是存储过程能做,而其他方式做不了的?

很简单,也有很多人提到过,就是性能好。 那么,为什么会性能好呢?

这与我们目前的软件结构有关系,在当前,大部分情况下,数据库是一台独立的机器,而应用服务器则是另外一台独立的机器,那么,相互独立的机器之间要进行交互操作,势必需要使用网络来进行通信。

网络通信的代价比使用内存指针变更的代价大非常多,这就导致了一个直接的问题,如果使用网络进行多次交互,那么延迟会远远地大于使用内存来进行消息交互。延迟变大,意味着锁持有时间变长,也就意味着单位时间内针对同一个数据的操作频率下降,TPS就会下降。 

这才是存储过程之所以能够提升性能的关键。 它不是恶魔,但也不是天使,能不能发挥出特定的优势,要看具体的业务场景需要。

我们做个简单的总结:

     存储过程的好处,就是可以减少网络交互开销,可以用来封装一些需要高性能的小的业务逻辑单元。

     存储过程的坏处,就是绑定到特定数据库上,同时,因为大部分存储过程是面向过程的代码,所以运维难度相对较大,不适于处理复杂业务逻辑。

 

第二个概念是:视图

视图这个概念也是我开始看数据库时候很晕的一个概念,在任何一个数据库内,数据库的说明文档中都会给出特别多中视图的实现,看起来就特别容易晕。经常有的困惑是: 为什么视图不能写数据? 以及,join本身也挺方便的的,我为什么还需要视图?

 

这里,为了解答这个问题,我们就需要来看看一种最常见的计算机优化方法: 将不确定性变成确定性。

很多情况下,如果你能提前预知不确定性的范围,往往就能大范围的减少锁的范围,或者将计算量进行分解。

视图,从一定程度上也是利用将不确定性变成确定性的方式,来实现join查询速度的优化和聚焦。

 

如果计算机不知道你预先需要把哪些表进行join操作,他能做的就只有使用最悲观的方式来对用户的行为进行假定,也就是最坏情况下,所有表都可能产生关联关系,并且关联的次数和频率都是均等的。那么针对这种场景,最安全的策略就是不缓存任何join的中间结果,而只使用通用的join算法进行join计算。

但是,如果用户通过自己的实际业务场景,发现其实有两个表是固定的被join在一起而进行查询的。 这种情况就符合了”将不确定性变成确定性“ 这个优化的前提,因此就可以进行一些优化,view从某种程度上来说,就是告知数据库这种确定性的一种手段。

数据库在获知这种hint后,就可以使用一些新的,空间换时间的方式,来预先进行一些操作,从而降低在join查询计算发生时所消耗的计算量。从而提升查询性能,降低系统开销。

 

ok,本篇到这,本篇主要是介绍了数据库的一些关键的概念,在下一篇,我将使用一些实际查询的例子,来帮助大家更易于理解在实际数据库中,上面的这些核心概念是如何被应用的。

时间: 2024-10-30 22:50:32

一个小型数据库的核心组件的相关文章

database-编程语言c、c++、c#、JAVA的应用前景及一个小型数据库开发需要哪些知识?

问题描述 编程语言c.c++.c#.JAVA的应用前景及一个小型数据库开发需要哪些知识? 在现阶段的网络应用开发.网页开发.电脑软件开发和手机的app开发中哪种编程语言应用的最为广泛? 目前在学习过程中已学习过c.JAVA和c#,但都是入门级的水平,之前在学习c时都在编写一些很无聊及无实际意义的程序,之后做JAVA的课程设计时,大部分的代码都是老师给的,只是让我们写其中的一些方法和类,现在正在学习c#,感觉上c#要比之前两种语言的开发过程更简单,现在主要集中在一些类似于记事本的窗口程序的开发设计

java+oracle小型数据库管理系统

问题描述 我想做一个小型数据库管理系统,前台用java或jsp写操作页面,后台用oracle数据库实现,不知道该怎么写,哪位大虾给写一下啊,内容可以是学籍管理系统或图书管理系统或小型商场商品管理等等,只要前台代码就行了,后台教我怎么连接操作就行了,具体的表格我可以自己设计

vb神童教程(续)--编写一个小型的信息管理系统

本文来演示一下如何用vb向数据库中添加.修改.删除记录这些操作.我觉得自己是比较菜的,几年来别人都在进步,只有我还在原地踏步.不过没有办法,我们这一圈人里现在只有我机器上还有vb6,勉为其难,只有尝试一下了.如果我写的这点幼稚的东西能为想要了解vb数据库操作的朋友提供哪怕是一丁点儿的参考和帮助,将是我最为高兴的事情,同时也希望高手不要见笑. 我做的这个实例名为"编程入门网网址管理系统",算是一个小型的信息管理系统吧.该系统后台使用的是Access数据库,程序中使用ADO代码链接的形式连

使用Snort和PHP构建一个小型网络防御系统

本文在Linux环境下,利用Snort和Iptables 构建了一个小型网络防御系统,由PHP页面提供了一个远程管理工具,并给出关键程序的实现和说明. 引言 Snort 是目前十分流行的轻型入侵检测系统.但是目前人们对Snort检测结果的处理大都停留在记录日志或简单通知网络管理员,由管理员进行审计再决定网络防御策略的阶段.Snort的检测结果并没有及时地用来抵御网络入侵.本文通过为Snort的报警输出模块提供一个服务监听程序的办法,及时获取Snort的报警信息并对其进行解析,根据解析结果向ipt

曙光领衔 秋季小型数据库服务器采购指南

凉爽的秋季让人便于思考:在这个数据为王的年代,重新审视数据战略的中小企业不在少数,有时候甚至能在颠覆常规分析思路下做出超越的结论.虽然中小型企业规模有限,但每天发生的各种业务,同样产生了大量数据.而一台经过硬件优化.软件测试,而量身打造的小型数据库服务器,不但可以发挥数据处理的效率,同时也是保护数据价值的最好家园. 小型数据库服务器采购:性价比最高 有人觉得,小型数据库不需要特殊采购服务器,随便找一台"差不多的"就行了.但到了业务系统真正上线的实际采购阶段,你会发现市场上的产品很少能够

一个操作数据库的Java Bean……

数据|数据库 一个操作数据库的Java Bean,有兴趣的朋友看一下吧~~ package dbconnect; import java.sql.*; public class sqlconnection { String sDbDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; String sConnStr = "jdbc:odbc:sqlconnect"; // sqlconnect 数据源名称: private Connecti

InnoDB 中文参考手册 --- 3 建立一个 InnoDB 数据库

参考|参考手册|数据|数据库|中文 InnoDB 中文参考手册 --- 犬犬(心帆)翻译 3 建立一个 InnoDB 数据库假设你已经安装了 MySQL 并且已经修改了 my.cnf 包含了必要的 InnoDB 参数设置 .在启动 MySQL 之前必须检查为InnoDB 指定的数据与日志文件路径是否存在以及在 这些目录上有足够的权限.InnoDB 不会自己建立目录,只能建立文件.同时检查是否有足够的磁盘空间存放数据与日志文件. 当创建一个 InnoDB 数据库时最好以命令行方式来运行 MySQL

C#反编译微软MSDN2003的帮助文档,并将反编译结果保存到一个SQLSERVER数据库中

server|sqlserver|编译|数据|数据库|微软 using System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms; namespace MSDNOUT{ /// <summary> /// 反编译微软MSDN2003文档并保存到数据库的程序主窗体 /// </summary> public class dlgM

在线等-求一个Struts和mybatis2个框架组成的一个小型的添加代码

问题描述 求一个Struts和mybatis2个框架组成的一个小型的添加代码 求一个Struts和mybatis2个框架组成的一个小型的添加代码 解决方案 http://blog.csdn.net/lwwgtm/article/details/9395841