Mongodb 性能测试_--__2__--的博客-程序员秘密

技术标签: 数据库_MongoDB  性能测试  mongodb  

转载地址  http://www.cnblogs.com/lovecindywang/archive/2011/03/02/1969324.html


进行了一下Mongodb亿级数据量的性能测试,分别测试如下几个项目:

(所有插入都是单线程进行,所有读取都是多线程进行)

1) 普通插入性能 (插入的数据每条大约在1KB左右)

2) 批量插入性能 (使用的是官方C#客户端的InsertBatch),这个测的是批量插入性能能有多少提高

3) 安全插入功能 (确保插入成功,使用的是SafeMode.True开关),这个测的是安全插入性能会差多少

4) 查询一个索引后的数字列,返回10条记录(也就是10KB)的性能,这个测的是索引查询的性能

5) 查询两个索引后的数字列,返回10条记录(每条记录只返回20字节左右的2个小字段)的性能,这个测的是返回小数据量以及多一个查询条件对性能的影响

6) 查询一个索引后的数字列,按照另一个索引的日期字段排序(索引建立的时候是倒序,排序也是倒序),并且Skip100条记录后返回10条记录的性能,这个测的是Skip和Order对性能的影响

7) 查询100条记录(也就是100KB)的性能(没有排序,没有条件),这个测的是大数据量的查询结果对性能的影响

8) 统计随着测试的进行,总磁盘占用,索引磁盘占用以及数据磁盘占用的数量

并且每一种测试都使用单进程的Mongodb和同一台服务器开三个Mongodb进程作为Sharding(每一个进程大概只能用7GB左右的内存)两种方案

其实对于Sharding,虽然是一台机器放3个进程,但是在查询的时候每一个并行进程查询部分数据,再有运行于另外一个机器的mongos来汇总数据,理论上来说在某些情况下性能会有点提高

基于以上的种种假设,猜测某些情况性能会下降,某些情况性能会提高,那么来看一下最后的测试结果怎么样?

备注:测试的存储服务器是 E5620  @ 2.40GHz,24GB内存,CentOs操作系统,打压机器是E5504 @ 2.0GHz,4GB内存,Windows Server 2003操作系统,两者千兆网卡直连。

image

从这个测试可以看出,对于单进程的方式:

1) Mongodb的非安全插入方式,在一开始插入性能是非常高的,但是在达到了两千万条数据之后性能骤减,这个时候恰巧是服务器24G内存基本占满的时候(随着测试的进行mongodb不断占据内存,一直到操作系统的内存全部占满),也就是说Mongodb的内存映射方式,使得数据全部在内存中的时候速度飞快,当部分数据需要换出到磁盘上之后,性能下降很厉害。(这个性能其实也不算太差,因为我们对三个列的数据做了索引,即使在内存满了之后每秒也能插入2MB的数据,在一开始更是每秒插入25MB数据)。Foursquare其实也是把Mongodb当作带持久化的内存数据库使用的,只是在查不到达到内存瓶颈的时候Sharding没处理好。

2) 对于批量插入功能,其实是一次提交一批数据,但是相比一次一条插入性能并没有提高多少,一来是因为网络带宽已经成为了瓶颈,二来我想写锁也会是一个原因。

3) 对于安全插入功能,相对来说比较稳定,不会波动很大,我想可能是因为安全插入是确保数据直接持久化到磁盘的,而不是插入内存就完事。

4) 对于一列条件的查询,性能一直比较稳定,别小看,每秒能有8000-9000的查询次数,每次返回10KB,相当于每秒查询80MB数据,而且数据库记录是2亿之后还能维持这个水平,性能惊人。

5) 对于二列条件返回小数据的查询,总体上性能会比4)好一点,可能返回的数据量小对性能提高比较大,但是相对来说性能波动也厉害一点,可能多了一个条件就多了一个从磁盘换页的机会。

6) 对于一列数据外加Sort和Skip的查询,在数据量大了之后性能明显就变差了(此时是索引数据量超过内存大小的时候,不知道是否有联系),我猜想是Skip比较消耗性能,不过和4)相比性能也不是差距特别大。

7) 对于返回大数据的查询,一秒瓶颈也有800次左右,也就是80M数据,这就进一步说明了在有索引的情况下,顺序查询和按条件搜索性能是相差无几的,这个时候是IO和网络的瓶颈。

8) 在整个过程中索引占的数据量已经占到了总数据量的相当大比例,在达到1亿4千万数据量的时候,光索引就可以占据整个内存,此时查询性能还是非常高,插入性能也不算太差,mongodb的性能确实很牛。

那么在来看看Sharding模式有什么亮点:

1) 非安全插入和单进程的配置一样,在内存满了之后性能急剧下降。安全插入性能和单进程相比慢不少,但是非常稳定。

2) 对于一个条件和两个条件的查询,性能都比较稳定,但条件查询性能相当于单进程的一半,但是在多条件下有的时候甚至会比单进程高一点。我想这可能是某些时候数据块位于两个Sharding,这样Mongos会并行在两个Sharding查询,然后在把数据进行合并汇总,由于查询返回的数据量小,网络不太可能成为瓶颈了,使得Sharding才有出头的机会。

3) 对于Order和Skip的查询,Sharding方式的差距就出来了,我想主要性能损失可能在Order,因为我们并没有按照排序字段作为Sharding的Key,使用的是_id作为Key,这样排序就比较难进行。

4) 对于返回大数据量的查询,Sharding方式其实和单进程差距不是很大,我想数据的转发可能是一个性能损耗的原因(虽然mongos位于打压机本机,但是数据始终是转手了一次)。

5) 对于磁盘空间的占用,两者其实是差不多的,其中的一些差距可能是因为多个进程都会多分配一点空间,加起来有的时候会比单进程多占用点磁盘(而那些占用比单进程少的地方其实是开始的编码错误,把实际数据大小和磁盘文件占用大小搞错了)。

测试最后的各个Sharding分布情况如下:

{
        "sharded" : true,
        "ns" : "testdb.test",
        "count" : 209766143,
        "size" : 214800530672,
        "avgObjSize" : 1024.0000011441311,
        "storageSize" : 222462757776,
        "nindexes" : 4,
        "nchunks" : 823,
        "shards" : {
                "shard0000" : {
                        "ns" : "testdb.test",
                        "count" : 69474248,
                        "size" : 71141630032,
                        "avgObjSize" : 1024.0000011515058,
                        "storageSize" : 74154252592,
                        "numExtents" : 65,
                        "nindexes" : 4,
                        "lastExtentSize" : 2146426864,
                        "paddingFactor" : 1,
                        "flags" : 1,
                        "totalIndexSize" : 11294125824,
                        "indexSizes" : {
                                "_id_" : 2928157632,
                                "Number_1" : 2832745408,
                                "Number1_1" : 2833974208,
                                "Date_-1" : 2699248576
                        },
                        "ok" : 1
                },
                "shard0001" : {
                        "ns" : "testdb.test",
                        "count" : 70446092,
                        "size" : 72136798288,
                        "avgObjSize" : 1024.00000113562,
                        "storageSize" : 74154252592,
                        "numExtents" : 65,
                        "nindexes" : 4,
                        "lastExtentSize" : 2146426864,
                        "paddingFactor" : 1,
                        "flags" : 1,
                        "totalIndexSize" : 11394068224,
                        "indexSizes" : {
                                "_id_" : 2969355200,
                                "Number_1" : 2826453952,
                                "Number1_1" : 2828403648,
                                "Date_-1" : 2769855424
                        },
                        "ok" : 1
                },
                "shard0002" : {
                        "ns" : "testdb.test",
                        "count" : 69845803,
                        "size" : 71522102352,
                        "avgObjSize" : 1024.00000114538,
                        "storageSize" : 74154252592,
                        "numExtents" : 65,
                        "nindexes" : 4,
                        "lastExtentSize" : 2146426864,
                        "paddingFactor" : 1,
                        "flags" : 1,
                        "totalIndexSize" : 11300515584,
                        "indexSizes" : {
                                "_id_" : 2930942912,
                                "Number_1" : 2835243968,
                                "Number1_1" : 2835907520,
                                "Date_-1" : 2698421184
                        },
                        "ok" : 1
                }
        },
        "ok" : 1
}

虽然在最后由于时间的关系,没有测到10亿级别的数据量,但是通过这些数据已经可以证明Mongodb的性能是多么强劲了。另外一个原因是,在很多时候可能数据只达到千万我们就会对库进行拆分,不会让一个库的索引非常庞大。在测试的过程中还发现几个问题需要值得注意:

1) 在数据量很大的情况下,对服务进行重启,那么服务启动的初始化阶段,虽然可以接受数据的查询和修改,但是此时性能很差,因为mongodb会不断把数据从磁盘换入内存,此时的IO压力非常大。

2) 在数据量很大的情况下,如果服务没有正常关闭,那么Mongodb启动修复数据库的时间非常可观,在1.8中退出的-dur貌似可以解决这个问题,据官方说对读取没影响,写入速度会稍稍降低,有空我也会再进行下测试。

3) 在使用Sharding的时候,Mongodb时不时会对数据拆分搬迁,这个时候性能下降很厉害,虽然从测试图中看不出(因为我每一次测试都会测试比较多的迭代次数),但是我在实际观察中可以发现,在搬迁数据的时候每秒插入性能可能会低到几百条。其实我觉得能手动切分数据库就手动切分或者手动做历史库,不要依赖这种自动化的Sharding,因为一开始数据就放到正确的位置比分隔再搬迁效率不知道高多少。个人认为Mongodb单数据库存储不超过1亿的数据比较合适,再大还是手动分库吧。

4) 对于数据的插入,如果使用多线程并不会带来性能的提高,反而还会下降一点性能(并且可以在http接口上看到,有大量的线程处于等待)。

5) 在整个测试过程中,批量插入的时候遇到过几次连接被远程计算机关闭的错误,怀疑是有的时候Mongodb不稳定关闭了连接,或是官方的C#客户端有BUG,但是也仅仅是在数据量特别大的时候遇到几次。

最新补充:在之后我又进行了几天测试,把测试数据量进一步加大到5亿,总磁盘占用超过500G,发现和2亿数据量相比,所有性能都差不多,只是测试6和测试7在超过2亿级别数据之后,每400万记录作为一个循环,上下波动30%的性能,非常有规律。



作者: lovecindywang     http://www.cnblogs.com/lovecindywang/archive/2011/03/02/1969324.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chuntian_feng/article/details/51871665

智能推荐

优秀的GitHub开源项目介绍_liuec1002的博客-程序员秘密

AdminLTE介绍AdminLTE是一款建立在bootstrap和jquery之上的开源的模板主题工具,它提供了一系列响应的、可重复使用的组件,并内置了多个模板页面;同时自适应多种屏幕分辨率,兼容PC和移动端。通过AdminLTE,我们可以快速的创建一个响应式的Html5网站。AdminLTE框架在网页架构与设计上,有很大的辅助作用,尤其是前端架构设计师,用好AdminLTE不但美观,而且可以免去写很大CSS与JS的工作量。2.GitHub获取AdminLTEhttps://github.co

MultipartFile上传文件报java.io.EOFException: Unexpected EOF read on the socket解决方法_Momo__zz的博客-程序员秘密

1、遇到的场景为: 上传文件偶尔会报出java.io.EOFException: Unexpected EOF read on the socket错误。 debug模式下不会出现该错误。2、我的情况:不需要创建文件流,只需要将文件转换成二进制存储进入数据库。3、解决方式: 3.1判断是否已经正确创建文件流。(我不需要。 ...

c语言程序题:统计某单词出现次数_c语言查找单词出现次数_nueroamazing的博客-程序员秘密

C笔记题目:编写程序,读取一段文本(以换行作为输入的结束),然后计算某个单词或单词的一部分(几个连续的字符)(也由用户输入)出现的次数。C#include<stdio.h>main(){char a[100],word[30];int i=0,j,na=0,nw=0,count=0,sum=0;while((a[i] = getchar()) != '\n'){//这里括号必须加,不然赋值优先级低于逻辑符号,数组里存的全是‘\0’na++;i++;}i=0;rewind

机器学习(周志华)学习笔记 - 调参和最终模型_调参与最终模型_「已注销」的博客-程序员秘密

1.大多数学习算法都有参数需要设定,参数的配置不同,学得的模型的性能不同。2.对每种参数配置都训练出模型,然后把对应最好模型的参数作为结果,这样的考虑基本是正确的有些参数是实数范围内取值, 不能穷举。 因此对每种参数都训练出来是不可能的,现实中常用的做法,是对每个参数选定一个范围和变化的步长 -- 如在 实数范围[0,0.2] 步长选0.05 则有 0 0.05 0.1 0.15 0...

matlab红色爱心,心形图的matlab实现_弗兰克乙醚的博客-程序员秘密

前两天在校内上分享了一篇文章,名为《一生只为等待能手绘这个函数给我的人》,看了点书,在网上又发了个帖子求助,后来做出了图片发给小白,还挺好玩的。首先谈一下隐函数的做图。心形图的笛卡尔坐标系形式为(x.^2+(9/4)*y.^2+z.^2-1).^3-x.^2.*z.^3-(9/80)*y.^2.*z.^3。fplot可以进行函数的做图,ezplot可以进行隐函数和多元函数的做图,fplot的一个程...

使用JohnTheRipper对有密码加密的ZIP压缩包文件进行暴力破解_ubuntu zip2john_江山灬如画的博客-程序员秘密

背景对加密的ZIP压缩包进行密码破解的方式有很多,网上也有很多文章,今天只介绍一种——JohnTheRipper。JohnTheRipper摘自百度百科: John the Ripper,是一个快速的密码破解工具,用于在已知密文的情况下尝试破解出明文的破解密码软件,支持目前大多数的加密算法。如DES、MD4、MD5等。它支持多种不同类型的系统架构,包括Unix、Linux、...

随便推点

Codeforce 431C - k-Tree(简单dp计数)_code 431c_阿狸是狐狸啦的博客-程序员秘密

题意:一颗满二叉树。每个点有k条边,边的权值为1~k,问你从root出发有多少种方案路径综合为n,且至少有一条边权值大于等于于d。思路:我们定义状态dp[i][j][k]=1;   表示当前在第i层,当前权值和为j,k为1表示已经有大于等于k的边 ,k为0表示还没有大于等于k的边 。dp[0][0][0]=1,然后就是简单的转移了。#include <bits/stdc++.h&g...

StringBuffer类--Arrays类--基本类型包装类_integer i1=new integer(97)_托尼韦恩的博客-程序员秘密

StringBuffer通过JDK提供的API,查看StringBuffer类的说明线程安全的可变字符序列StringBuffer和String的qubie1.String是一个不可变字符序列2.StringBuffer是一个可变的字符序列StringBuffer的添加功能1.public StringBuffer append(String str):可以把任意类型数据添加到字符串缓冲区里面,并...

nvidia-docker无法正常启动_nvidia-docker无响应_xieyan0811的博客-程序员秘密

上周更新了nv的驱动到450,然后发现nvidia-docker无法启动了,报错:docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "process_linux.go:449: container init caused \"process_linux.go:432: running prestart hook

Focal Visual-Text Attention for Visual Question Answering论文笔记_bxg1065283526的博客-程序员秘密

Abstract神经网络对语言和视觉的最新见解已经成功地应用于简单的单图像视觉问题回答。然而,为了解决诸如个人照片等多媒体收藏中的现实问题,我们必须用一系列照片或视频来观察整个收藏。当回答来自大量集合的问题时,一个自然的问题是识别支持答案的片段。在本文中,我们描述了一种新的神经网络,称为焦点视觉文本注意网络(FVTA),用于视觉问题回答中的集体推理,其中视觉和文本序列信息,例如图像和文本元数据...

安卓 图片清晰度 判断_抖音短视频素材、图片、音乐、文案怎么找,工具用哪些(新手必备)..._weixin_39702639的博客-程序员秘密

亲爱的知友你好,我是阿信,专注于短视频运营及变现已经快两年,这期间也和很多新手朋友去交流沟通过,发现很多人在找素材这一块就把自己难住了,找不到好的素材,做不出优质的视频,对此今天就花时间给大家分享一下短视频常用工具和素材网站。一、视频素材二、图片素材三、音效配音素材四、文案素材五、视频制作工具六、数据分析工具一、视频素材比如操作抖音励志号、影视号、音乐号等很多领域的视频创作,需要用到的视频素材,很...

小菜鸟之网络基础1_auu93902的博客-程序员秘密

网络原理图IEEE0x30-48-5c单播:unicast 组播 广播DHCPMAC(物理地址) 6个字节IPV4 4个字节IPV6 16个字节60-14-B3-C1-74-6D60-14-B3 厂商号C1-74-6D流水号192.168.3.4/255.255.255.0 左边全1,右边全0A:192.168.3.4 255.255.255.0B:192.168.2.711000...

推荐文章

热门文章

相关标签