内存数据库FastDB和SQLite性能测评 - 数据库 - 三路友社论坛 娱乐交友社区论坛 - SNS
返回列表 回复 发帖

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

一、引言
在很多项目中,经常会碰到这样的需求,需要对大量数据进行快速存储、查询、删除等操作,特别是在一些针对诸如运营商、银行等大型企业的应用中,这些需求尤为常见。比如智能网中的大量在线并发用户的数据管理、软交换平台中的在线信息交互、宽带/3G等数据网中在线用户行为记录等等。
针对这些情形,我们通常需要选择高性能的数据库产品,而且通常需要使用内存数据库,顾名思义,内存数据库指的是所有的数据访问控制都在内存中进行,这是与磁盘数据库相对而言的,磁盘数据库虽然也有一定的缓存机制,但都不能避免从外设到内存的交换,而这种交换过程对性能的损耗是致命的,目前主流数据库如SYBASE、ORACLE等都有这种缓存机制,如将特定表绑定一定的缓存,从而在一定程度上改善数据吞吐性能。而内存数据库几乎可以完全避免这种内外存数据交换的发生,特别是在物理内存足够大的设备上尤其如此,通常这种数据库也被称为主存数据库(Main Memory DataBase, MMDB)。
二、主存数据库比较
目前比较知名的商业内存数据库有,ORACLE的TimesTen,MCObject的eXtremeDB、韩国的Altibase等,这些数据库产品性能都非常的强劲,当然价格也相当的强劲,在非特大型系统建设时,通常让人望而却步。于是退而求其次,免费开源内存数据库给了我们第二种选择。Berkeley DB,SQLite,MonetDB,FastDB,H2等,不一而足。本文主要针对SQLite和FastDB进行性能测评。
2.1 测试准备
首先,笔者通过对评测数据的调研发现,通常认为,BDB性能不如SQLite,参考“免费的实时数据库,我们该选谁?—-BerkeleyDB与SQLite评测对比 ”
上文中还提到,“据说FastDB很快,但数据库大小不能大于物理内存…”,于是笔者对FastDB产生了兴趣,从FastDB作者的网站看到关于这点的介绍,并不是说数据库大小不能大于物理内存,而是说数据库大小超过物理内存时,性能与不超过时相比会有一定的降低(降低幅度未作说明,估计是不推荐使用)。幸运地是,目前物理内存实在说不上贵,服务器内存在10G之上都是很正常的事情了。因此可以根据具体项目数据量需求来确定是否能使用FastDB,比如并不是所有的表都需要放在内存中。下面即将描述的测试表明,一旦使用FastDB,其性能在免费MMDB产品中绝对可执牛耳。由于已经有人对BDB和SQLite进行过比较,因此下面仅将FastDB与其中的优胜者SQLite进行性能测评。SQLite采用内存模式,即打开数据库使使用“:memory:”参数,此时SQLite不产生数据库文件,所有操作都在内存中,这一点需要特殊说明,与之不同的是,FastDB有两种模式,磁盘模式和无盘模式,前者会产生磁盘文件,后者则与SQLite的内存模式相同。
说是测评,其实过程也很简单,无非是设计测试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的搜索结果也能看出。社区的不成熟会带来学习成本的增加,这一点在选型时也需要考虑。
Taii Wang @ Xi’an

附录:针对commit时sync到文件导致效率降低问题的官方权威解决方法
评测过程中,针对commit的效率问题,笔者向FastDB作者进行了邮件咨询,本文完成之后,收到了回复,这应该是最权威的solution了,附上交互邮件内容供参考:
咨询邮件,Taii to Knizhnik
Title: a question about the peformance of transaction in fastdb
HI expert,
I run the testperf example of fastdb on my notebook, and i found that when I changed the mechanism of the transaction from batch-mode to one-by-one mode, then the result degrades to: "Elapsed time for inserting 10000 record: 61 seconds", from "Elapsed time for inserting 10000 record: 62 ms".
followed is the modification :
        for (i = 0; i < nRecords; i++) {
            Record rec;
            key = (3141592621u*key + 2718281829u) % 1000000007u;
            sprintf(buf, INT8_FORMAT ".", key);
            rec.key = buf;
            rec.value = buf;
            insert(rec);
        db.commit();
        }
        printf("Elapsed time for inserting %d record: %d seconds\n",
               nRecords, int(time(NULL) - start));
        start = time(NULL);
        //db.commit()
How can i deal with the problem? I must use one-by-one commit in my project. Thanks great.

Thanks/Taii @ China
回复邮件:Knizhnik to Taii

Hi Taii,
Commit is very expensive operation because it requires synchronous write to the disk
which is very expensive operation (average disk access time for modern disks is about 10msec, it means that we can not
perform more than 100 writes in random locations on the disk).
You can dramatically increase transaction commit time if you set
no_sync flag in fileOpenFlags field of OpenParameters structure:
OpenParameter params;
params. databaseName = "…";
params. databaseFilePath = "…";

params.fileOpenFlags = dbFile::no_sync;
db.open(params);
In this case FastDB will not flush disk buffers at commit.
It can cause loose of the committed changes or even corruption of the database in case of power failure or operating system fault.
But crash of the application itself can not cause any problems in this mode.
同时,向FastDB的作者Knizhnik致以真挚的谢意,不仅仅是为他快速专业的reply,更为他对开源社区做出的贡献!(Acknowlegement : My thanks go to the author of FastDB, Kinzhnik. not only for his fast and professional reply, but also for his great contributions to the open source world .)
大家可能都会认为,要想学好英语口语,练就一口纯正的口语英语,当然要去模仿纯正的,标准的发音啦。但是事实上却是相反的,我们用日本人的一个试验来说明。
  日本人是出了名的英语说的难听,发音不标准,是什么原因造成的呢?很多人答曰日本人舌头硬。其实日本人跟大家一样,舌头并不特殊,发音不准的原因是因为他们的日语造成的。大家都知道英语有大约44个发音(元音加辅音),而日语只有大约30个。(按照标准音图,日语是有50个音的,但是有一些音实际上是相同的,没什么区别)于是日本人在说英文时,很多音是发不出来的。比如“日 r”的音,日语中没有,所以不会说。很常用的read and write,日本人只能说成 lead and light,用“l”代替“r”,是个很典型的例子。为了找到确切的原因,有人做了这样一个实验,让这些日本人听许多“r”或“l”打头的词(不给看拼写),二选一的答案,做完了测试,发现大家的正确率是50%。各位已经发现问题了,二选一能答对一半,实际就是根本不会,纯粹瞎懵,命中率当然是一半。这个结果说明,这些日本人根本就没有听出来这些音的区别,这就可以理解他们说不准的原因了,即然都分不出区别,怎么可能说出区别。
  其实发音不准主要是因为耳朵听不准这件事,大家是有实际观察经验的。比如有人唱歌走调,是什么原因呀?是不是嗓子不好?不是,主要是耳朵听不准,所以唱歌走调的人唱完了觉得自己唱得挺对的,你们怎么都说我走调呢?原因是他们的耳朵听不准音,自己听不出走调了。(如果您唱歌不走调,自己堵上耳朵唱一个试试,别人保证说您走调了)。
  科学实验告诉我们,只有小孩子的耳朵对各种语言有高分辨率,才可以听准任何语言的发音而模仿到位,成年人不行了。具体说,大多数人到十二岁以上就不行了,这个能力失去了。这就导致了成年人为了纠正外语发音时或提高发音准确度,单纯听和模仿标准外语发音不行,因为做不到,所以如何纠正成年人的发音的最重要环节就是提高成年人的听音准确度。而实践经验证明,多听各种各样的发音,有助于成年人提高听力敏感度和分辨力,从而达到定准和自然纠正自己发音的效果。
        在这里给大家推荐一款超分贝英语学习软件,其中的语音内容非常丰富,发音的有男的、女的、老的、少的,而且都是实际的语音氛围,在学习的过程中能够听到各种风格的发音,而且在学习时压力不大,但是实际效果却非常好,不但可以提高英语听力的分辨能力,提高实战水平,而且还能够应对各种英语考试,适合多年龄层次的人员学习英语。其范围包括:幼儿英语少儿英语儿童英语小学英语初级 英语初中英语高中英语高考英语职称英语大学英语英语四级考研英语商务英语外贸英语等等。
         超分贝英语网站:www.yiEnglish.com 注:如果您觉得本文对你有用,欢迎告诉您的朋友。转载请以链接的形式注明出处。
“2010年女性新标准,上得了厅堂,下得了厨房,杀得了木马,翻得了围墙,开得起好车,买得起好房,斗得过小三,打得过流氓。祝广大的女同胞们节日快乐!”刻章  根雕 床上用品 核雕

成功女性新标准:
    撒过泼、出过轨、勾引领导下过水。
    装过神、弄过鬼,跟人老公亲过嘴。
    傍过款、出过洋,带着网友开过房。
    翻过窗、跳过墙,一夜睡过三张床。
大发娱乐城网上娱乐,您爱上我了吗?
在赌场里面,很多玩家都是爱赌场的,当然,也有很多玩家是憎恨赌场的。
其实,这所有的爱与恨,都来自于玩家本身。赢了就爱,输了就恨。http://www.dafayule.com 有一位久经赌场30余年的资深玩家说:其实每个玩家都不是跟赌场来赌,实际上是跟自己来赌,赌自己的情绪,赌自己的自控能力,赌自己的运气和技巧。因为投注什么,投注多少,什么时候投注,什么时候收手…都是玩家说了算,也就是说输赢都是由玩家自己决定的。
赌场是一个很锻炼人性情的地方,也是一个看人品的地方。赢了就爱,输了就恨,臭骂,说粗口,数别人祖宗,问候别人器官…所以,作为一个成熟的玩家,一定要很清晰自己的消费能力,用娱乐消遣的心态来享受博彩带来的刺激,这才是赌的最高境界。
当然,以上所言,都是要针对在公平公正的赌场而言。
无论您爱赌场也好,恨赌场也好,如果是在一个没有作弊的,公平公正的赌场里享受了博彩所带来的刺激,那么,爱和恨都已属泰然了。
领有菲律宾特颁合法经营执照,隶属于于英国上市的亚洲博彩集团ASIANLOGIC旗下,, http://www.dafayule.com采用第三方提供的真人视频投注系统,该投注系统是目前亚洲最具权威性的,已提供给多家世界品牌公司同时使用,使用此游戏系统的所有公司,只要是同一张台同一局牌开彩结果都是一致的,公平公正,绝不存在作弊空间。
大发娱乐拥有庞大的专业客服系统,每天24小时在线贴心服务;财务系统每天有效运作,每一笔款项都要经过BOD的验证,服务器存放在合法经营的菲律宾数据中心,客户的所有资料受严密管理,在任何情况绝不透露给如政府等第三方。
大发娱乐不单可免除玩家奔赴各陆地赌场的劳逸,而且还经常举办优惠活动,让玩家直接得益。
今天,您爱我吗?   大发扑克
奥恩美业荣登2011年胶原蛋白排行榜10强之首
网易网:www.3loo.com/link.php?url=http://news.163.com/11/0729/17/7A56DSID00014AEE.html
搜狐网:www.3loo.com/link.php?url=http://roll.sohu.com/20110729/n314925048.shtml
东莞时间网:www.3loo.com/link.php?url=http://news.timedg.com/2011-07/29/content_5480479.htm
重庆晨网:www.3loo.com/link.php?url=http://www.cqcb.com/cbnews/instant/2011-07-29/1724033.html
新民网:www.3loo.com/link.php?url=http://news.xinmin.cn/rollnews/2011/07/29/11565234.html
第一食品网:www.3loo.com/link.php?url=http://www.foods1.com/content/1191218/


奥恩美业品牌胶原蛋白荣登热卖排行榜

网易网:www.3loo.com/link.php?url=http://news.163.com/11/0729/17/7A56E5DL00014AEE.html
东莞时间网:www.3loo.com/link.php?url=http://news.timedg.com/2011-07/29/content_5480480.htm
重庆晨网:www.3loo.com/link.php?url=http://www.cqcb.com/cbnews/instant/2011-07-29/1724029.html
新民网:www.3loo.com/link.php?url=http://news.xinmin.cn/rollnews/2011/07/29/11565235.html  
第一食品网:www.3loo.com/link.php?url=http://www.foods1.com/content/1191217/

淘宝胶原蛋白排行榜揭露口碑好的胶原蛋白产品
网易网:www.3loo.com/link.php?url=http://news.163.com/11/0729/15/7A4VKOPA00014AEE.html
中国古都网:www.3loo.com/link.php?url=http://www.zggdw.net/n1365448c14.aspx  
重庆晨网:www.3loo.com/link.php?url=http://www.cqcb.com/cbnews/instant/2011-07-29/1722628.html
新民网:www.3loo.com/link.php?url=http://news.xinmin.cn/rollnews/2011/07/29/11563234.html  
第一食品网:www.3loo.com/link.php?url=http://www.foods1.com/content/1190968/
返回列表