您好,欢迎访问一九零五行业门户网

内存数据库FastDB和SQLite性能测评

说是测评,其实过程也很简单,无非是设计测试case,编写测试code,输出测试result,最后做出结论。通常我们认为带索引的插入耗时相对 于查询和删除来说比较长,因此首先来看插入性能。采用一个简单的表来完成接下来的所有测试,表中仅包含两个字段,integer
说是测评,其实过程也很简单,无非是设计测试case,编写测试code,输出测试result,最后做出结论。通常我们认为带索引的插入耗时相对 于查询和删除来说比较长,因此首先来看插入性能。采用一个简单的表来完成接下来的所有测试,表中仅包含两个字段,integer intkey,和varchar strkey。测试平台为window7 32bit系统(evaluation copy 7127),编译器vc6 sp6。在dell inspiron 640m上运行,cpu为intel core 2 cpu t5500 @ 1.66ghz,内存2.5g。
对fastdb(采用磁盘模式),表结构的定义如下:
class _testtable 

public: 
    db_int8 intkey; 
    char const* strkey; 
    type_descriptor((key(intkey, indexed), key(strkey, indexed))); 
};
register(_testtable);
对sqlite,建表sql如下:
create table [_testtable] ( [intkey] integer  not null primary key, [strkey] varchar(50)  null)
2.2 不同事务模式下的插入性能比较
2.2.1 fastdb磁盘模式
我们首先按照批量事务处理的模式将intkey从1到nrecords(记录条数),并指定相应的strkey,分别调用相应的接口(均为原始 api)插入到两张表中,这里的批量事务处理模式指的是,比如插入10000条记录,插第一条之前开始事务,最后一条之后结束事务。此时在插入不同数目记 录时的表现分别如下(一万条、十万条、72万条、一百万条):
批量事务提交:
e:\intrest\fastdb\perftest\debug>perftest.exe 
[fastdb] elapsed time for inserting 10000 record: 63 ms 
[sqlite] elapsed time for inserting 10000 record: 639 ms
e:\intrest\fastdb\perftest\debug>del *.fdb (清除测试生成数据,重新测试,下同。)
e:\intrest\fastdb\perftest\debug>perftest.exe 
[fastdb] elapsed time for inserting 100000 record: 1186 ms 
[sqlite] elapsed time for inserting 100000 record: 6318 ms
e:\intrest\fastdb\perftest\debug>del *.fdb
e:\intrest\fastdb\perftest\debug>perftest.exe 
[fastdb] elapsed time for inserting 7200000 record: 152460 ms 
[sqlite] elapsed time for inserting 7200000 record: 560121 ms
e:\intrest\fastdb\perftest\debug>perftest.exe 
[fastdb] elapsed time for inserting 1000000 record: 15522 ms 
[sqlite] elapsed time for inserting 1000000 record: 67423 ms
从上我们可以看出,在批量事务模式下,fastdb比sqlite的插入性能提高了3-10倍。但是在很多情况下,我们可能会需要逐条逐条的事务提交,下面给出了逐条事务模式的测试结果:
e:\intrest\fastdb\perftest\debug>perftest.exe 
[fastdb] elapsed time for inserting 10000 record: 57315 ms(这个太恐怖了,不调整的话没法使用) 
[sqlite] elapsed time for inserting 10000 record: 780 ms
e:\intrest\fastdb\perftest\debug>perftest.exe (sqlite显式分条事务) 
[fastdb] elapsed time for inserting 10000 record: 59967 ms 
[sqlite] elapsed time for inserting 10000 record: 1154 ms
从上我们可以看出,fastdb在这种情形下的性能急遽降低,降到一个几乎不能接收的水平。经过对fastdb的源代码分析(开源的好处体现出来 了),发现fastdb在每次事务提交时,都会将变更的数据内容同步到磁盘文件中(这是因为我们采用了磁盘模式),因此造成性能的显著降低。
直观上看,解决fastdb的这个问题有两种办法,一是避免每次事务提交时同步到磁盘,因为在这种应用中,这种同步操作并不需要实时进行,通常每隔 一段时间同步一次就可以了(比如1s、1min、等根据具体项目的可靠性需要);二是使用前面提到的fastdb无盘(diskless)模式。
我们首先来看第一种方案,通过search fastdb文档(文档和社区是fastdb的一个软肋),我们发现作者已经考虑到了这个问题,fastdb为数据库提供了precommit的接口,用 于完成除sync到磁盘文件外的所有事物操作,如释放mutex资源等。同时提供了backup接口,用来完成内存数据到磁盘文件的备份,甚至支持打开数 据库时同时指定定时备份到磁盘文件的间隔。这样一来,每次事务提交的效率理论上会得到大大提高,并且通过定时备份机制可以保证数据的可靠性。我们来看使用 precommit进行逐条事务提交时fastdb的表现:
e:\intrest\fastdb\perftest\debug>perftest(使用precommit逐条提交事务) 
[fastdb] elapsed time for inserting 10000 record: 62 ms 
[sqlite] elapsed time for inserting 10000 record: 1170 ms
e:\intrest\fastdb\perftest\debug>perftest 
[fastdb] elapsed time for inserting 100000 record: 1170 ms 
[sqlite] elapsed time for inserting 100000 record: 11747 ms
e:\intrest\fastdb\perftest\debug>perftest 
[fastdb] elapsed time for inserting 1000000 record: 8081 ms 
[sqlite] elapsed time for inserting 1000000 record: 125768 ms
从上可以看出,在逐条事务模式下,通过使用precommit技术,fastdb性能比sqlite提高了10倍左右。当然也许有读者怀疑加了备份 机制之后的性能,确实笔者没有进行这项测试,但是,需要注意的是,fastdb在数据库关闭时会强制sync到磁盘文件,但sqlite没有这种功能,同 时,在进行这项测试时,两种数据库都没有定时备份机制,因此该比较是公平的。
2.2.2 fastdb无盘模式
再来看第二种方案,fastdb采用无盘(通过编译选项控制生成diskless版本)模式,此时fastdb初始化一段共享内存(shmat or mmap),这个初始大小通常很大,并且运行期不能扩展(无盘模式的劣势)。我们将初始共享内存设置为1g,得到的测试结果如下:
e:\intrest\fastdb\perftest\debug>perftest.exe 
[fastdb] elapsed time for inserting 100000 record: 624 ms (批量事务提交) 
[sqlite] elapsed time for inserting 100000 record: 11544 ms
e:\intrest\fastdb\perftest\debug>perftest.exe 
[fastdb] elapsed time for inserting 100000 record: 7410 ms (逐条事务提交) 
[sqlite] elapsed time for inserting 100000 record: 11560 ms
e:\intrest\fastdb\perftest\debug>perftest.exe 
[fastdb] elapsed time for inserting 1000000 record: 134660 ms 
[sqlite] elapsed time for inserting 1000000 record: 120167 ms
e:\intrest\fastdb\perftest\debug>perftest.exe 
[fastdb] elapsed time for inserting 250000 record: 23666 ms 
[sqlite] elapsed time for inserting 250000 record: 29110 ms
从上我们可以看出,无盘模式在大数据量下的表现与sqlite相近,这一点不是很好理解,需要研究diskless的设计模式,理论上应该与 precommit模式性能相近。但是实践是检验真理的唯一标准。我们可以看出,磁盘模式的precommit方式性能表现卓越,不管从横向还是纵向来 看。
2.3 查询性能比较
下面的比较都使用磁盘模式的precommit方式,再来看索引查询的性能表现,测试时都是先插入十万条数据后,再分别对该十万条数据进行查询,需 要注意的是我们同时对fastdb是否增加hash索引的性能进行了横向测评,fastdb增加hash索引很简单,通过修改type- descriptor来完成,上面的class中改为type_descriptor((key(intkey, indexed), key(strkey, indexed)));即为intkey增加了hash索引。
e:\intrest\fastdb\perftest\debug>perftest (fastdb哈希索引) 
[fastdb] elapsed time for inserting 100000 record: 624 ms 
[fastdb] elapsed time for 100000 index searches: 328 ms 
[sqlite] elapsed time for inserting 100000 record: 10312 ms 
[sqlite] elapsed time for 100000 index searches: 10935 ms
e:\intrest\fastdb\perftest\debug>perftest(fastdb非哈希索引) 
[fastdb] elapsed time for inserting 100000 record: 577 ms 
[fastdb] elapsed time for 100000 index searches: 515 ms 
[sqlite] elapsed time for inserting 100000 record: 10343 ms 
[sqlite] elapsed time for 100000 index searches: 9532 ms
从测试结果可以看出,查询十万条索引记录的效率,fastdb要比sqlite快20倍左右,并且在增加hash索引后能够得到进一步的改善。
2.4 删除性能比较及综合表现
最后,我们在测试删除效率时,同时综合来看fastdb与sqlite之间插入、查询、删除的性能表现:
插入、查询、删除综合比较:
e:\intrest\fastdb\perftest\debug>perftest(批量删除,fastdb.removeall(),sqlite.delete*) 
[fastdb] elapsed time for inserting 100000 record: 608 ms 
[fastdb] elapsed time for 100000 index searches: 687 ms 
[fastdb] elapsed time for deleting all 100000 records: 16 ms 
[sqlite] elapsed time for inserting 100000 record: 11107 ms 
[sqlite] elapsed time for 100000 index searches: 10062 ms 
[sqlite] elapsed time for deleting all 100000 records: 16 ms
e:\intrest\fastdb\perftest\debug>perftest(逐条删除) 
[fastdb] elapsed time for inserting 100000 record: 593 ms 
[fastdb] elapsed time for 100000 index searches: 562 ms 
[fastdb] elapsed time for deleting all 100000 records one by one: 905 ms 
[sqlite] elapsed time for inserting 100000 record: 10406 ms 
[sqlite] elapsed time for 100000 index searches: 10249 ms 
[sqlite] elapsed time for deleting all 100000 records one by one: 8923 ms
从上可以看出,就删除效率而言,批量删除的速度二者相近,而逐条删除时,十万条记录的删除累积,fastdb比sqlite快了10倍左右。
2.5 总结
优点:fastdb磁盘模式下,采用precommit方式,性能远远优于sqlite,并且fastdb提供了完善的备份恢复机制,能够保证数据 安全。fastdb的无盘模式在小数据量时表现优越,并且不会产生磁盘数据文件,也不能加载已经保存的数据库文件,看起来更像是针对嵌入式设备(如智能手 机、pda等)开发的,对于这种场景可以考虑使用无盘模式。
缺点:fastdb目前能够search到的比较著名的应用是pingtel公司的开源统一通信产品sipx,该产品采用的是fastdb的磁盘模 式。这可能多少与fastdb的完全授权模式有关,而sqlite采用的是gpl的不允许闭源的商业发布。当然主要还是社区的不成熟,这从google trends的搜索结果也能看出。社区的不成熟会带来学习成本的增加,这一点在选型时也需要考虑。
其它类似信息

推荐信息