当前位置:文档之家› 开源内存数据库的调研与分析

开源内存数据库的调研与分析

一、内存数据库具备的一些基本功能1):数据的管理,内存数据库机制是支持永久数据的管理的,包括数据库的的定义、存储、维护等功能。

2):数据的操作,内存数据库支持对数据进行增,删,改,查,数据完整性校验等一些基本功能。

3):事务管理,内存数据库支持调度,进程间、线程间的一些并发等操作。

4):数据恢复备份机制,内存数据库支持在线备份和系统崩溃后的自动恢复。

二、FastDBFastDB是一个高效率的内存数据库系统,在磁盘上的数据库文件和使用该数据库的每一个应用程序占用的虚拟内存空间相映射,这样取消了数据文件和缓冲池中的数据传输。

再将整个文件数据读入内存,并且使用了高性能的锁工具实现了只读模式线程间、单个更改模式线程和多个只读模式线程间的并发执行。

FastDB通过位图实现对内存进行分配,最小单位块是分配量子(16字节)。

如此大大提高了数据引用的局部性(对象数据尽可能分配在连续的内存区域),最小化了修改页的数目和减少了事务提交时间。

事务提交协议基于一个影子根页算法,对数据库执行原子更新操作,恢复效率很高,在存储数据结构上可以采用T-tree结构(T-tree和A VL-tree相似,只是T-tree中每个节点中顺序存储了多个值),对于大量相似重复性数据的查询性能相当高;也可以采用Hash存储,这是用关键字段定位表中记录的最好办法(采用等号进行查询)。

影子根页算法概述:FastDB数据库中每条对象都具有唯一的标识符(OID),用作一个数组(对象索引)的下标,元素值表示对象的一个句柄,在FastDB数据库中存在两个索引(当前索引和影子索引),当某个对象第一次被修改时,它会创建一个副本,当前索引中的对象句柄被修改指向副本,影子索引仍然包含一个指向该对象原始版本的句柄。

所有更改发生在副本上,FastDB在对象索引的一个特殊位图页上标记出哪个索引包含修改过的对象句柄。

当一个事务被提交时,FastDB首先检查对象索引的尺寸的大小,若增长了,还会重新为对象索引的影子副本重新分配内存,然后释放“旧对象”占用的内存,释放后,将修改过的所有位图页flush到磁盘上,然后FastDB将改变数据库头部中的当前对象索引指示符,以切换对象索引的角色。

当前对象索引将变成影子索引之后,FastDB 把修改过的所有句柄从新的对象索引中复制到先前是影子的、现在已成为当前的对象索引中。

此时,两个索引都得到了同步。

优点:具备实时能力及便利的C++接口。

FastDB针对应用程序通过控制读访问模式作了优化。

通过降低数据传输的开销和非常有效的锁机制提供了高速的查询。

对每一个使用数据库的应用数据库文件被影射到虚拟内存空间中。

因此查询在应用的上下文中执行而不需要切换上下文以及数据传输。

fastdb中并发访问数据库的同步机制通过原子指令实现,几乎不增加查询的开销。

fastdb假定整个数据库存在于RAM中,并且依据这个假定优化了查询算法和接口。

此外,fastdb 没有数据库缓冲管理开销,不需要在数据库文件和缓冲池之间传输数据。

Fastdb支持事务、在线备份以及系统崩溃后的自动恢复。

事务提交协议依据一个影子根页面算法来自动更新数据库。

恢复可以执行得非常快,为临界应用提供了高可用性。

此外,取消事务日志改进了整个系统的性能,并且使得可以更有效的利用系统资源。

fastdb是一个面向应用的数据库,数据库表通过应用程序的类信息来构造。

fastdb支持自动的模式评估。

fastdb提供一个灵活方便的接口来从数据库中获取数据。

使用一个类SQL的查询语言进行指定的查询。

通过一些后关系特性如非原子字段,嵌套数组,用户定义类型和方法,对象间直接引用简化了数据库应用程序的设计并使之更有效率。

缺点:尽管fastdb的优化是立足于假定整个数据库配置在计算机的物理内存中,但是也有可能出现使用的数据库的大小超过了系统物理内存的大小的情况,在这种情况下标准的操作系统交换机制就会工作。

但是整个fastdb的搜索算法和结构是建立在假定所有的数据都存在于内存中的,因此数据换出的效率不会很高。

FastDB不支持client-server架构因而所有使用FastDB的应用程序必须运行在同一主机上。

部署方法:应用程序编译环境需求,首先是任何一个FastDB应用程序必须包含头文件:fastdb.h;然后是可以选择调用库文件(FastDB编译后提供静态库(libfastdb_r.a)和共享库两种库(libfastdb_r.so/ libfastdb_r.so.2)给调用);最后是FastDB提供很多编译选项接口,用户可以根据需要进行设置,比如:容错支持,无盘模式,锁检测清理机制等等功能。

运行系统环境需求:理论上说,内存加载的数据库文件规模最小是1MB,上限就是内存和磁盘的容量了(FastDB 的整个优化设计是基于真个数据库系统存放在机器物理内存中,但是它依然支持将应用在规模超过物理内存的数据库上,只是效率不会很高)接口调用方法:1):打开或创建数据库:dbDatabase db(parameter);db.open(parameter);mode的有:dbReadOnly,dbAllAccess,dbConcurrentRead,dbConcurrentUpdate四模式2):FastDB支持的数据类型:类型描述bool 布尔类型(true,false)int1 一个字节的带符号整型(-128..127)int2 两个字节的带符号整型(-32768..32767)int4 四个字节的带符号整型(-2147483648..2147483647)int8 八个字节的带符号整型(-2**63..2**63-1)real4 四个字节的ANSI 浮点型real8 八个字节的双精度浮点型char const* 非中断整型dbReference<T> 到类T 的指针dbArray<T> 元素类型是T 的动态数组3):FastDB对表的接口描述C++需要用类的形式来定义表结构,然后一一映射到表的fields,如果类有方法就得用宏:CLASS_DESCRIPTOR(name,field_list),进行描述,还有方法宏TYPE_DESCRIPTOR(field_list)最后只需要将类进行注册:REGISTER(Class Name);4):游标游标有两种模式:dbCursorViewOnly,dbCursorForUpdate定义举例dbCursor<Class Name> instance (dbCursorForUpdate);性能测试:不同事务模式下的插入性能比较:1):磁盘模式我们首先按照批量事务处理的模式将intKey从1到nRecords(记录条数),并指定相应的strKey,分别调用相应的接口(均为原始API)插入到两张表中,这里的批量事务处理模式指的是,比如插入10000条记录,插第一条之前开始事务,最后一条之后结束事务。

此时在插入不同数目记录时的表现分别如下(一万条、十万条、72万条、一百万条):批量事务提交:E:\intrest\FastDB\PerfTest\Debug>PerfTest.exe[FASTDB] Elapsed time for inserting 10000 record: 63 msE:\intrest\FastDB\PerfTest\Debug>PerfTest.exe[FASTDB] Elapsed time for inserting 100000 record: 1186 msE:\intrest\FastDB\PerfTest\Debug>PerfTest.exe[FASTDB] Elapsed time for inserting 7200000 record: 152460 msE:\intrest\FastDB\PerfTest\Debug>PerfTest.exe[FASTDB] Elapsed time for inserting 1000000 record: 15522 ms逐条事务模式:E:\intrest\FastDB\PerfTest\Debug>PerfTest.exe[FASTDB] Elapsed time for inserting 10000 record: 57315 msE:\intrest\FastDB\PerfTest\Debug>PerfTest.exe[FASTDB] Elapsed time for inserting 10000 record: 59967 ms从中可以看出,FastDB在这种情形下的性能急遽降低,降到一个几乎不能接收的水平。

原因是因为FastDB在每次事务提交时,都会将变更的数据内容同步到磁盘文件中,因此造成性能的显著降低。

直观上看,解决FastDB的这个问题有两种办法,一是避免每次事务提交时同步到磁盘,因为在这种应用中,这种同步操作并不需要实时进行,通常每隔一段时间同步一次就可以了(比如1S、1Min、等根据具体项目的可靠性需要);二是使用前面提到的FastDB无盘(DISKLESS)模式。

对于第一种方案,FastDB为数据库提供了precommit的接口,用于完成除sync到磁盘文件外的所有事物操作。

同时提供了backup接口,用来完成内存数据到磁盘文件的备份,甚至支持打开数据库时同时指定定时备份到磁盘文件的间隔。

这样一来,每次事务提交的效率理论上会得到大大提高,并且通过定时备份机制可以保证数据的可靠性。

使用precommit进行逐条事务提交:E:\intrest\FastDB\PerfTest\Debug>PerfTest[FASTDB] Elapsed time for inserting 10000 record: 62 msE:\intrest\FastDB\PerfTest\Debug>PerfTest[FASTDB] Elapsed time for inserting 100000 record: 1170 msE:\intrest\FastDB\PerfTest\Debug>PerfTest[FASTDB] Elapsed time for inserting 1000000 record: 8081 ms2):FastDB无盘模式FastDB采用无盘(通过编译选项控制生成DISKLESS版本)模式,此时FastDB初始化一段共享内存(shmat or mmap),这个初始大小通常很大,并且运行期不能扩展(无盘模式的劣势)。

将初始共享内存设置为1G,得到的测试结果如下:E:\intrest\FastDB\PerfTest\Debug>PerfTest.exe[FASTDB] Elapsed time for inserting 100000 record: 624 ms (批量事务提交)E:\intrest\FastDB\PerfTest\Debug>PerfTest.exe[FASTDB] Elapsed time for inserting 100000 record: 7410 ms (逐条事务提交)E:\intrest\FastDB\PerfTest\Debug>PerfTest.exe[FASTDB] Elapsed time for inserting 1000000 record: 134660 msE:\intrest\FastDB\PerfTest\Debug>PerfTest.exe[FASTDB] Elapsed time for inserting 250000 record: 23666 ms查询性能比较:下面都使用磁盘模式的precommit方式,再来看索引查询的性能表现,测试时都是先插入十万条数据后,再分别对该十万条数据进行查询,同时对FastDB是否增加HASH索引的性能进行了横向测评,FastDB增加HASH索引很简单,通过修改TYPE- DESCRIPTOR来完成,上面的class中改为TYPE_DESCRIPTOR((KEY(intKey, INDEXED), KEY(strKey, INDEXED)));即为intKey增加了Hash索引。

相关主题