零 环境说明:
所有的数据插入的都是Key=int,Value=int,在循环中递增的.
本机NTFS的默认簇大小为4K.
本机配置仅仅影响绝对值.相对值是可比较的:
OS=WinXP SP2;RAM=1G;CPU=AMD Athlon 64 X2 Dual 5000+;Disk=160G
测试的实际数据量为:300*10000*2*sizeof(int)/1024/1024~=22.89MByte
下面所有的测试结果的单位都是秒.
编译器: C++ builder 6.0(使用bcb编译BDB源码,形成LIB库后,直接链接到测试程序中.没有测试DLL的形式.)
BDB版本:4.6.21.NC
一 测试页尺寸对读写性能的影响:
记录数量 =300万 缓存尺寸=0M
读写\页尺寸 | 1K | 2K | 4K | 8K | 16K | 32K |
B+写 | 94.94 | 84.83 | 82.73 | 97.16 | 142.67 | 232.11 |
HASH写 | 346.16 | 320.41 | 288.36 | 295.19 | 599.66 | 867.03 |
B+读 | 4.22 | 4.06 | 3.86 | 3.91 | 3.80 | 3.78 |
HASH读 | 8.25 | 7.94 | 5.42 | 5.41 | 4.99 | 4.88 |
结论:页尺寸与文件系统的簇大小相同时,写入性能最佳,读取性能中等.
在0M缓存的时候,B+的性能要比HASH好得多.
二 测试cache缓存大小对读写性能的影响:
记录数量=300万 页尺寸=4K 真实数据量=22.89MByte 数据库文件大小=80M
读写\缓存 | 0M | 10M | 20M | 40M | 80M | 160M | 320M |
B+写 | 85.06 | 88.66 | 133.31 | 164.81 | 15.31 | 15.34 | 15.27 |
HASH写 | 292.91 | 224.47 | 180.76 | 95.28 | 20.11 | 20.06 | 20.05 |
B+读 | 3.98 | 4.17 | 4.86 | 9.56 | 3.83 | 3.81 | 3.80 |
HASH读 | 5.53 | 5.83 | 5.83 | 8.16 | 5.20 | 5.08 | 5.16 |
记录数量=600万 页尺寸=4K 真实数据量=45.78MByte 数据库文件大小=160M
读写\缓存 | 0M | 40M | 80M | 160M | 320M |
B+写 | 259.39 | 1198.27 | 1017.94 | 34.59 | 34.30 |
HASH写 | 1889.32 | 1279.95 | 563.12 | 40.67 | 40.89 |
B+读 | 7.89 | 14.02 | 22.84 | 7.97 | 8.03 |
HASH读 | 11.17 | 16.81 | 11.66 | 10.39 | 10.88 |
结论:
对于缓存大于数据库文件尺寸的时候,没有太多可说的,操作都在内存中,速度非常快.
对于大数据量的读取,两组对比都比较清晰的说明了一点:缓存的大小对读取记录的性能影响不是很大.
对于大数据量的写入,缓存对性能的影响就非常可观了,基本可以肯定的是,HASH库缓存越大写入速度越快. 而奇怪的是,B+库在缓存不足的时候,性能反而比0缓存时还要差很多!!
总的来说,在我的这些测试中,B+与HASH数据库的性能差异很大.
对于缓存大于物理内存的情况未做测试,估计对性能不会有好的影响,毕竟在这种情况下,效率的瓶颈都是在磁盘的IO上.
测试的核心代码如下:
#include <db_cxx.h>
#define DATABASE "access.db"
//tcount=记录数为多少万次,DbType=数据库类型,psize=页尺寸K,csize=缓存尺寸M
void run(int tcount,DBTYPE DbType,size_t psize,size_t csize)
{
remove(DATABASE);
Db db(0, 0);
db.set_errpfx("AccessExample");
db.set_pagesize(1024*psize);
db.set_cachesize(0, 1024*1024*csize, 0);
db.open(NULL, DATABASE, NULL, DbType, DB_CREATE|DB_THREAD, 0664);
int testcount=10000*tcount;
size_t tick1=GetTickCount();
for (int i=0;i<testcount;i++)
{
Dbt key(&i,sizeof(int));
Dbt data(&i,sizeof(int));
db.put(0, &key, &data, DB_NOOVERWRITE);
}
printf("插入结束 %d 万记录,全部用时:%.2f秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);
tick1=GetTickCount();
try
{
Dbc *dbcp;
db.cursor(NULL, &dbcp, 0);
Dbt key;
Dbt data;
while (dbcp->get(&key, &data, DB_NEXT) == 0)
{
key.get_data();
data.get_data();
}
dbcp->close();
printf("遍历结束 %d 万记录,全部用时:%.2f秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);
db.sync(0);
}
catch (DbException &dbe) {}
db.close(0);
}