woaidongmao

文章均收录自他人博客,但不喜标题前加-[转贴],因其丑陋,见谅!~
随笔 - 1469, 文章 - 0, 评论 - 661, 引用 - 0
数据加载中……

对Berkeley DB的性能进行的部分测试

 

零 环境说明:

    所有的数据插入的都是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上.

测试的核心代码如下:

 

Cpp代码 clip_image001 clip_image003clip_image004

  1. #include <db_cxx.h>  
  2. #define DATABASE    "access.db"  
  3. //tcount=记录数为多少万次,DbType=数据库类型,psize=页尺寸K,csize=缓存尺寸M  
  4. void run(int tcount,DBTYPE DbType,size_t psize,size_t csize)  
  5. {  
  6.     remove(DATABASE);  
  7.     Db db(0, 0);  
  8.  
  9.     db.set_errpfx("AccessExample");  
  10.     db.set_pagesize(1024*psize);  
  11.     db.set_cachesize(0, 1024*1024*csize, 0);  
  12.     db.open(NULL, DATABASE, NULL, DbType, DB_CREATE|DB_THREAD, 0664);  
  13.  
  14.     int testcount=10000*tcount;  
  15.     size_t tick1=GetTickCount();  
  16.     for (int i=0;i<testcount;i++)  
  17.     {  
  18.         Dbt key(&i,sizeof(int));  
  19.         Dbt data(&i,sizeof(int));  
  20.         db.put(0, &key, &data, DB_NOOVERWRITE);  
  21.     }  
  22.       
  23.     printf("插入结束 %d 万记录,全部用时:%.2f秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);  
  24.     tick1=GetTickCount();  
  25.     try 
  26.     {  
  27.         Dbc *dbcp;  
  28.         db.cursor(NULL, &dbcp, 0);  
  29.         Dbt key;  
  30.         Dbt data;  
  31.         while (dbcp->get(&key, &data, DB_NEXT) == 0)  
  32.         {  
  33.             key.get_data();  
  34.             data.get_data();  
  35.         }  
  36.         dbcp->close();  
  37.         printf("遍历结束 %d 万记录,全部用时:%.2f秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);  
  38.         db.sync(0);  
  39.     }  
  40.     catch (DbException &dbe) {}  
  41.     db.close(0);  
  42. } 
#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);
}

 

分享到: clip_image005clip_image006

关于一些中文分词器

评论

4 楼 h_rain 2009-02-22  

结论:页尺寸与文件系统的簇大小相同时,写入性能最佳,读取性能中等.

缓存用尽后,性能的瓶颈就在于磁盘IO.
BDB
内部对IO进行了优化,每次操作都是对"页尺寸"字节进行处理,就是说,读写10字节或100字节的时候,其实都是在"页尺寸"这么大的内存上进行读写,之后一次性将一个页写入磁盘.你给定的页尺寸是8k,但ntfs默认的"簇"大小是4k,所以这样的操作要跨簇进行,效率就低了.

建议根据文件系统的"簇"大小设置BDB的"页尺寸".
这样的话,耗时基本是定长的了.

3 楼 peter_wu 2009-02-20  

观察任务管理器,发现速度快的时候,cache还没有用完,没有IO操作。当内存不再增长,cache用完的时候,IO开始大量读取和写入,速度开始下降。原来如此啊。

2 楼 peter_wu 2009-02-20  

插入一个周期,10w 用时 0.00 秒
插入一个周期,10w 用时 0.92 秒
插入一个周期,10w 用时 1.09 秒
插入一个周期,10w 用时 1.11 秒
插入一个周期,10w 用时 1.14 秒
插入一个周期,10w 用时 1.16 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.14 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.28 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.17 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.26 秒
插入一个周期,10w 用时 1.24 秒
插入一个周期,10w 用时 1.16 秒
插入一个周期,10w 用时 1.17 秒
插入一个周期,10w 用时 1.38 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.16 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.17 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.17 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.28 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.33 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.23 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.23 秒
插入一个周期,10w 用时 1.42 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.27 秒
插入一个周期,10w 用时 5.84 秒
插入一个周期,10w 用时 9.52 秒
插入一个周期,10w 用时 14.03 秒
插入一个周期,10w 用时 15.39 秒
插入一个周期,10w 用时 16.44 秒
插入一个周期,10w 用时 20.39 秒
插入结束 500 万记录,全部用时:156.05秒
遍历结束 500 万记录,全部用时:14.11秒
请按任意键继续. . .

1 楼 peter_wu 2009-02-20  

我改了下代码,发现一个问题,随着时间推移,插入效率下降严重,请问是为什么。

Java代码 clip_image001 clip_image003clip_image004

  1. #include <db_cxx.h>    
  2. #include <Windows.h>  
  3. #define DATABASE    "access.db"    
  4. void run(int tcount,DBTYPE DbType,size_t psize,size_t csize)  ;  
  5. void main(int argc,char * argv[])  
  6. {  
  7.     run(500,DB_BTREE,8,100);  
  8. }  
  9.  
  10.  
  11. //tcount=记录数为多少万次,DbType=数据库类型,psize=页尺寸K,csize=缓存尺寸M    
  12. void run(int tcount,DBTYPE DbType,size_t psize,size_t csize)    
  13. {    
  14.     remove(DATABASE);    
  15.     Db db(0, 0);    
  16.  
  17.     db.set_errpfx("AccessExample");    
  18.     db.set_pagesize(1024*psize);    
  19.     db.set_cachesize(0, 1024*1024*csize, 0);    
  20.     db.open(NULL, DATABASE, NULL, DbType, DB_CREATE|DB_THREAD, 0664);    
  21.  
  22.     int testcount=10000*tcount;    
  23.     size_t tick1=GetTickCount();    
  24.  
  25.     DWORD inlinetick=tick1;  
  26.     for (int i=0;i<testcount;i++)    
  27.     {    
  28.         Dbt key(&i,sizeof(int));    
  29.         Dbt data(&i,sizeof(int));    
  30.         db.put(0, &key, &data, DB_NOOVERWRITE);    
  31.         if (i%100000==0)  
  32.         {  
  33.             printf("插入一个周期,10w 用时 %.2f 秒\n",(GetTickCount()-inlinetick)/(float)1000);  
  34.             inlinetick=GetTickCount();  
  35.         }  
  36.     }    
  37.  
  38.     printf("插入结束 %d 万记录,全部用时:%.2f秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);    
  39.     tick1=GetTickCount();    
  40.     try    
  41.     {    
  42.         Dbc *dbcp;    
  43.         db.cursor(NULL, &dbcp, 0);    
  44.         Dbt key;    
  45.         Dbt data;    
  46.         while (dbcp->get(&key, &data, DB_NEXT) == 0)    
  47.         {    
  48.             key.get_data();    
  49.             data.get_data();    
  50.         }    
  51.         dbcp->close();    
  52.         printf("遍历结束 %d 万记录,全部用时:%.2f秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);    
  53.         db.sync(0);    
  54.     }    
  55.     catch (DbException &dbe) {}    
  56.     db.close(0);    
  57. }   

 

posted on 2011-08-28 16:22 肥仔 阅读(3910) 评论(0)  编辑 收藏 引用 所属分类: 数据库