paulwong

Mongodb 查询性能的事情

上一篇: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

Indexing and Query Optimizer (Aaron Staple)
ps:

默认 mongodb 服务器只有10个并发,如果要提高它的连接数,可以用 --maxConns num 来提高它的接收并发的数据。

mongodb 的 java 驱动默认最多只有 10 并发连接池。要提高它,可以在 mongo.jar 的环境中加入 MONGO.POOLSIZE 系统参数,如 java -DMONGO.POOLSIZE=50 ...

posted on 2015-01-06 23:39 paulwong 阅读(711) 评论(0)  编辑  收藏 所属分类: 性能优化MONGODB


只有注册用户登录后才能发表评论。


网站导航: