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的搜索结果也能看出。社区的不成熟会带来学习成本的增加,这一点在选型时也需要考虑。
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com