作者:业余爱好者 | 来源:互联网 | 2014-05-28 16:53
上一篇:MongodbVSMysql查询性能,测试了mongodb与mysql的查询性能。结果说明mongodb性能可以,可以代替mysql来使用。但是这个测试都是在百万级别,我的场景在KW级别。所以还要对mongodb在kw级别下测试效果。我测试环境是4G内存(有好
上一篇:Mongodb VS Mysql 查询性能,测试了 mongodb 与 mysql 的查询性能。结果说明 mongodb
性能可以, 可以代替 mysql 来使用。
但是这个测试都是在百万级别,我的场景在 KW 级别。所以还要对 mongodb 在 kw 级别下测试效果。
我测试环境是 4G 内存(有好些内存被其它程序占用),2kw 数据,查询随机生成 id(一次查询 20 个id)。
在这样的环境中测试不理想,比较失望。平均一次查询 500ms(比 mysql
还差,特别是在并发查询下,性能较差。很底的吞吐量)。查看其索引大小(用 db.mycoll.stats() 可以查询):2kw
数据中有 1.1G 左右的索引,存储的数据在 11G 左右。
测试过程中发现 iowait 占 50% 左右,看来还是 io 的瓶颈。还看到 mongodb
使用的内存不多(小于索引的大小,看来这机器不足够来测试)。
换了个有可用 6G 内存的机器。在 50 个并发下,可以达到平均 100 ms
左右,算比较满意,但是并发好像能力不够强。但这个性能不能由我控制,还由机器的可用内存控制。原因就是 mongodb
没有指定可占用的内存大小,它把所有空闲内存当缓存使用,既是优点也是缺点:优点--可以最大限度提升性能;缺点--容易受其它程序干扰(占用了它的缓存)。由我测试来看,它抢占内存的能力不强。mongodb
是用内存映射文件 vmm,官方的说明:
Memory Mapped Storage Engine
This is the current storage engine for MongoDB, and it uses
memory-mapped files for all disk I/O. Using this strategy,
the operating system's virtual memory manager is in charge of
caching. This has several implications:
There is no redundancy between file system cache and database
cache: they are one and the same.
MongoDB can use all free memory on the server for cache space
automatically without any configuration of a cache size.
Virtual memory size and resident size will appear to be very
large for the mongod process. This is benign: virtual memory
space will be just larger than the size of the datafiles open and
mapped; resident size will vary depending on the amount of memory
not used by other processes on the machine.
Caching behavior (such as LRU'ing out of pages, and laziness of
page writes) is controlled by the operating system: quality of the
VMM implementation will vary by OS.
所以这么来看,我觉得 mongodb
没有指定内存大小来保证正常的缓存是个缺点。应该至少保证索引全部能放到内存中。但这个行为不是由启动程序决定,而是由环境决定(美中不足)。
官方也有段内容说到索引放到内存中:
If your queries seem sluggish, you should verify that your
indexes are small enough to fit in RAM. For instance, if you're
running on 4GB RAM and you have 3GB of indexes, then your indexes
probably aren't fitting in RAM. You may need to add RAM and/or
verify that all the indexes you've created are actually being
used.
还是希望 mongodb 中可以指定内存大小,确保它有足够内存加载索引。
小结:大数据量下(kw级)mongodb 并发查询不够理想(100-200/s)。写数据很快(我的环境,远程提交近
1w/s,估计达到 1.5W/s 是没问题的,基本不受大数据量的影响)。
贴个测试数据:
|
1 id(内存使用 <1.5g)
|
10 id(内存使用 2-3g)
|
20 id(内存使用 >4g)
|
1
|
2
|
3
|
1
|
2
|
3
|
1
|
2
|
3
|
total time
|
17.136
|
25.508
|
17.387
|
37.138
|
33.788
|
25.143
|
44.75
|
31.167
|
30.678
|
1 thread thruput
|
583.5668
|
392.0339
|
575.1423
|
269.266
|
295.9631
|
397.725
|
223.4637
|
320.8522
|
325.9665
|
|
|
|
|
|
|
|
|
|
|
total time
|
24.405
|
22.664
|
24.115
|
41.454
|
41.889
|
39.749
|
56.138
|
53.713
|
54.666
|
5 thread thruput
|
2048.76
|
2206.142
|
2073.398
|
1206.156
|
1193.631
|
1257.893
|
890.6623
|
930.8733
|
914.6453
|
|
|
|
|
|
|
|
|
|
|
total time
|
27.567
|
26.867
|
28.349
|
55.672
|
54.347
|
50.93
|
72.978
|
81.857
|
75.925
|
10 thread thruput
|
3627.526
|
3722.038
|
3527.461
|
1796.235
|
1840.028
|
1963.479
|
1370.276
|
1221.643
|
1317.089
|
|
|
|
|
|
|
|
|
|
|
total time
|
51.397
|
57.446
|
53.81
|
119.386
|
118.015
|
76.405
|
188.962
|
188.034
|
138.839
|
20 thread thruput
|
3891.278
|
3481.53
|
3716.781
|
1675.238
|
1694.7
|
2617.63
|
1058.414
|
1063.637
|
1440.517
|
|
|
|
|
|
|
|
|
|
|
total time
|
160.038
|
160.808
|
160.346
|
343.559
|
352.732
|
460.678
|
610.907
|
609.986
|
1411.306
|
50 thread thruput
|
3124.258
|
3109.298
|
3118.257
|
1455.354
|
1417.507
|
1085.357
|
818.4552
|
819.6909
|
354.2818
|
|
|
|
|
|
|
|
|
|
|
total time
|
2165.408
|
635.887
|
592.958
|
1090.264
|
1034.057
|
1060.266
|
1432.296
|
1466.971
|
1475.061
|
100 thread thruput
|
461.8067
|
1572.606
|
1686.46
|
917.209
|
967.0647
|
943.1595
|
698.1797
|
681.6767
|
677.9381
|
上面的测试分别用三种查询(每次 1,10,20 id),在不同并发下测试3次,每次发出 1w
次查询。第一行数据为所有线程累加时间(单位 ms),第二行数据为吞吐量(1w /(total time / thread
num))。测试中内存使用慢慢增加,所以后面的数据可能比较高效的(高效的环境)。
从上表看,10 - 20线程比较高的吞吐量。看到内存使用,前提就是索引加载到内存中,并有些内存作为缓存。
下面有个索引查询优化的 pdf。
Indexing and Query Optimizer
ps:
默认 mongodb 服务器只有10个并发,如果要提高它的连接数,可以用 --maxConns num
来提高它的接收并发的数据。
mongodb 的 java 驱动默认最多只有 10 并发连接池。要提高它,可以在 mongo.jar 的环境中加入
MONGO.POOLSIZE 系统参数,如 java -DMONGO.POOLSIZE=50 ...