在九月初的时候,RMongoDB正式发布了修订版本,这也就意味着,从事数值计算的语言也可以于Nosql产品相接轨了,但是鉴于我身边并没有公司真的在使用R和MongoDB的结合,所以在效率问题上,我们也不敢掉以轻心,所以就做了一个这样的测试。

 

测试环境是8核,64位机。 用于测试的库是一个未经Sharding,大概30G左右的Collection。用于存储用户的喜好信息,标签信息等数据。 

 

1 library(rmongodb) 
      
    
 2  
     
 3 mongo <- mongo.create() 
     
 4  
     
 5  
     if(mongo. 
     is.connected(mongo)) 
     
 6 { 
     
 7     ns <-  
     ' 
     rivendell.user 
     ' 
     
 8      
     print( 
     ' 
     查询一个没有索引的字段,查询一条 
     ') 
     
 9      
     print(system.time(p <- mongo.find.one(mongo,ns,list(Friend=600)))) 
     
10      
     print( 
     ' 
     查询一个没有索引的字段,多条,without buffer 
     ') 
     
11      
     print(system.time(p <- mongo.find(mongo,ns,list(Friend=600)))) 
     
12      
     print( 
     ' 
     看看是否有缓存策略 
     ') 
     
13      
     print(system.time(p <- mongo.find(mongo,ns,list(Friend=600)))) 
     
14  
     
15      
     print( 
     ' 
     查询一个没有索引的字段,多条,has buffer 
     ') 
     
16     buf <- mongo.bson.buffer.create() 
     
17     mongo.bson.buffer.append(buf, 
     ' 
     Friend 
     ',600L) 
     
18     query <- mongo.bson. 
     from.buffer(buf) 
     
19      
     print(system.time(p <- mongo.find(mongo,ns,query))) 
     
20      
     print( 
     ' 
     看看是否有缓存策略 
     ') 
     
21     buf <- mongo.bson.buffer.create() 
     
22     mongo.bson.buffer.append(buf, 
     ' 
     Friend 
     ',600L) 
     
23     query <- mongo.bson. 
     from.buffer(buf) 
     
24      
     print(system.time(p <- mongo.find(mongo,ns,query))) 
     
25  
     
26      
     print( 
     ' 
     大于的查询,查询一条记录 
     ') 
     
27      
     print(system.time(p <- mongo.find.one(mongo,ns,list(Friend=list( 
     ' 
     $gt 
     '=600L))))) 
     
28      
     print( 
     ' 
     大于的记录,查询多条记录 
     ') 
     
29      
     print(system.time(cursor <- mongo.find(mongo,ns,list(Friend=list( 
     ' 
     $gt 
     '=600L))))) 
     
30     mongo.cursor.destroy(cursor) 
     
31  
     
32      
     print( 
     ' 
     查询一条有索引的记录 
     ') 
     
33      
     print(system.time(p <- mongo.find.one(mongo,ns,list( 
     ' 
     _id 
     '=3831809L)))) 
     
34      
     print( 
     ' 
     查询索引的记录 
     ') 
     
35      
     print(system.time(p <- mongo.find(mongo,ns,list( 
     ' 
     _id 
     '=3831809L)))) 
     
36  
     
37      
     print( 
     ' 
     插入一条记录 
     ') 
     
38     buf <- mongo.bson.buffer.create() 
     
39     mongo.bson.buffer.append(buf, 
     ' 
     name 
     ', 
     " 
     huangxin 
     ") 
     
40     mongo.bson.buffer.append(buf, 
     ' 
     age 
     ',22L) 
     
41     p <- mongo.bson. 
     from.buffer(buf) 
     
42      
     print(system.time(mongo.insert(mongo,ns,p))) 
     
43  
     
44      
     print( 
     ' 
     找到刚刚插入的记录 
     ') 
     
45      
     print(system.time(p <- mongo.find.one(mongo,ns,list( 
     ' 
     name 
     '= 
     ' 
     huangxin 
     ')))) 
     
46      
     if(! 
     is.null(p)) 
     
47     { 
     
48          
     print( 
     ' 
     success 
     ') 
     
49     } 
     
50  
     
51      
     print( 
     ' 
     批量插入 
     ') 
     
52  
     
53     buf <- mongo.bson.buffer.create() 
     
54     mongo.bson.buffer.append(buf, 
     ' 
     name 
     ', 
     ' 
     huangxin 
     ') 
     
55     mongo.bson.buffer.append(buf, 
     ' 
     age 
     ',22L) 
     
56     p1 <- mongo.bson. 
     from.buffer(buf) 
     
57  
     
58     buf <- mongo.bson.buffer.create() 
     
59     mongo.bson.buffer.append(buf, 
     ' 
     name 
     ', 
     ' 
     huangxin 
     ') 
     
60     mongo.bson.buffer.append(buf, 
     ' 
     age 
     ',22L) 
     
61     p2 <- mongo.bson. 
     from.buffer(buf) 
     
62  
     
63     buf <- mongo.bson.buffer.create() 
     
64     mongo.bson.buffer.append(buf, 
     ' 
     name 
     ', 
     ' 
     huangxin 
     ') 
     
65     mongo.bson.buffer.append(buf, 
     ' 
     age 
     ',22L) 
     
66     p3 <- mongo.bson. 
     from.buffer(buf) 
     
67  
     
68      
     print(system.time(mongo.insert.batch(mongo,ns,list(p1,p2,p3)))) 
     
69  
     
70      
     print( 
     ' 
     找到刚刚批量插入的记录 
     ') 
     
71      
     print(system.time(cursor <- mongo.find(mongo,ns,list( 
     ' 
     name 
     '= 
     ' 
     huangxin 
     ')))) 
     
72  
     
73     i <- 0 
     
74      
     while(mongo.cursor.next(cursor)) 
     
75     { 
     
76         i <- i + 1 
     
77     } 
     
78      
     print(i) 
     
79  
     
80      
     print( 
     ' 
     批量更新 
     ') 
     
81      
     print(system.time(mongo.update(mongo,ns,list(name= 
     ' 
     huangxin 
     '),list( 
     ' 
     name 
     '=  
     ' 
     kym 
     ')))) 
     
82  
     
83      
     print( 
     ' 
     查看更新是否成功 
     ') 
     
84      
     print(system.time(p <- mongo.find.one(mongo,ns,list( 
     ' 
     name 
     '= 
     ' 
     kym 
     ')))) 
     
85      
     if(! 
     is.null(p)) 
     
86     { 
     
87          
     print( 
     ' 
     success 
     ') 
     
88     } 
     
89  
     
90      
     print( 
     ' 
     批量删除 
     ') 
     
91      
     print(system.time(mongo.remove(mongo,ns,list(name= 
     ' 
     kym 
     ')))) 
     
92 } 
     
93  
     
94      
     print(system.time(p <- mongo.find.one(mongo,ns,list( 
     ' 
     name 
     '= 
     ' 
     kym 
     ')))) 
     
95      
     if(! 
     is.null(p)) 
     
96     { 
     
97          
     print( 
     ' 
     success 
     ') 
     
98 
 
 
 
 
 
 
" 
   查询一个没有索引的字段,查询一条 
   " 
   
 user system elapsed 
   
 0.000 0.000 0.115 
   
 [1]  
   " 
   查询一个没有索引的字段,多条,without buffer 
   " 
   
 user system elapsed 
   
 0.000 0.000 32.513 
   
 [1]  
   " 
   看看是否有缓存策略 
   " 
   
 user system elapsed 
   
 0.000 0.000 32.528 
   
 [1]  
   " 
   查询一个没有索引的字段,多条,has buffer 
   " 
   
 user system elapsed 
   
 0.000 0.000 32.685 
   
 [1]  
   " 
   看看是否有缓存策略 
   " 
   
 user system elapsed 
   
 0.000 0.000 33.172 
   
 [1]  
   " 
   大于的查询,查询一条记录 
   " 
   
 user system elapsed 
   
 0.000 0.000 0.001 
   
 [1]  
   " 
   大于的记录,查询多条记录 
   " 
   
 user system elapsed 
   
 0.000 0.000 0.014 
   
 [1]  
   " 
   查询一条有索引的记录 
   " 
   
 user system elapsed 
   
 0 0 0 
   
 [1]  
   " 
   查询索引的记录 
   " 
   
 user system elapsed 
   
 0 0 0 
   
 [1]  
   " 
   插入一条记录 
   " 
   
 user system elapsed 
   
 0 0 0 
   
 [1]  
   " 
   找到刚刚插入的记录 
   " 
   
 user system elapsed 
   
 0.00 0.00 35.42 
   
 [1]  
   " 
   success 
   " 
   
 [1]  
   " 
   批量插入 
   " 
   
 user system elapsed 
   
 0 0 0 
   
 [1]  
   " 
   找到刚刚批量插入的记录 
   " 
   
 user system elapsed 
   
 0.004 0.000 35.934 
   
 [1] 7 
   
 [1]  
   " 
   批量更新 
   " 
   
 user system elapsed 
   
 0.000 0.004 0.000 
   
 [1]  
   " 
   查看更新是否成功 
   " 
   
 user system elapsed 
   
 0.000 0.000 67.773 
   
 [1]  
   " 
   success 
   " 
   
 [1]  
   " 
   批量删除 
   " 
   
 user system elapsed 
   
 0 0 0 
   
 user system elapsed 
   
 0.000 0.000 91.396

 

之前我一直不太理解的就是为什么大于和等于,差距会差这么多。后来当我在用Python去做同样的测试的时候发现,Python两者的效率其实是相同的,所以这就证明了这个不是MongoDB的问题,而我不相信在数据库层面,一个语言的Driver会有这么大的差别。

后来我发现了Python和R的关于MongoDB Driver的一个区别。首先,Python find的时候,不是将查询到的数据集整体拉回,而是返回一个cursor,也就是说,他在执行find命令的时候并不消耗时间,而如果加上while cursor.next()的时候,才会真正地去执行这个查询。

但是R不一样,R会首先考虑数据集的大小(或者其他情况),然后视情况而定地返回cursor还是将整个数据集整体拉回。如果我们将之前的while mongo.cursor.next(cursor)也算在计算时间的时候,那么我们就会发现,其实大于和等于的操作,效率相差并不明显了.......

 

在实际操作中,批量插入是一个非常常见的应用场景,但是对于R或者Matlab语言来说,循环的效率一直是硬伤,所以接下来,我会尝试着用apply系列来解决R语言的循环问题,如果实际操作发现可行,那么接下来使用mutilab等R的并行计算库来充分发挥多核的效率也值得尝试了!