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);  
#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 肥仔 阅读(3669) 评论(0)  编辑 收藏 引用 所属分类: 数据库


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理