文档章节

Mongodb亿级数据量的性能测试

今幕明
 今幕明
发布于 2014/06/24 15:34
字数 2670
阅读 193
收藏 19
点赞 0
评论 0

进行了一下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%的性能,非常有规律。


本文转载自:http://www.cnblogs.com/lovecindywang/archive/2011/03/02/1969324.html?ADUIN=48141341&ADSESSION=140...

共有 人打赏支持
今幕明
粉丝 45
博文 224
码字总数 39350
作品 0
朝阳
程序员
redis, memcached, mongo性能比较

1、性能 都比较高,性能对我们来说应该都不是瓶颈 总体来讲,TPS方面redis和memcache差不多,要大于mongodb 2、操作的便利性 memcache数据结构单一 redis丰富一些,数据操作方面,redis更好一...

无精疯 ⋅ 04/23 ⋅ 0

面对Schema free的MongoDB,如何规范你的schema

作为近年最为火热的文档型数据库,MongoDB受到了越来越多人的关注,但是由于国内的MongoDB相关技术分享屈指可数,不少朋友都在抱怨无从下手。本期【DBA+社群】联合发起人周李洋为大家分享面对...

周李洋 ⋅ 2016/01/15 ⋅ 0

存储大量爬虫数据的数据库,了解一下?

"当然, 并不是所有数据都适合" 在学习爬虫的过程中, 遇到过不少坑. 今天这个坑可能以后你也会遇到, 随着爬取数据量的增加, 以及爬取的网站数据字段的变化, 以往在爬虫入门时使用的方法局限性...

fesoncn ⋅ 04/09 ⋅ 0

MongoDB 3.0新特性概述

MongoDB 在 2015年3月3日 跳过了 MongoDB 2.8版本,直接在 MongoDB 2.6版本后,发布了MongoDB 3.0版本。 随后在 2015年3月17日 发布了 MongoDB 3.0.1 版本; 在 2015年4月9日发布了 MongoDB ...

xinsir999 ⋅ 05/02 ⋅ 0

MongoDB 4.0 RC 版本强势登陆

MongoDB 因其灵活的文档模型、可扩展分布式设计广受开发者喜爱,在此基础上,MongoDB 4.0 推出了更强大的功能支持,目前4.0第一个RC版本已经发布,本文将介绍 MongoDB 4.0 核心的一些新特性。...

张友东 ⋅ 05/30 ⋅ 0

MongoDB中的explain和hint提的使用

一、简介 这里简单介绍一下各个工具的使用场景,一般用mysql,redis,mongodb做存储层,hadoop,spark做大数据分析。 mysql适合结构化数据,类似excel表格一样定义严格的数据,用于数据量中,...

踏雪无痕SS ⋅ 02/22 ⋅ 0

MongoDB 4.0 首个 RC 版发布,支持多文档事务

MongoDB 因其灵活的文档模型、可扩展分布式设计广受开发者喜爱,在此基础上,MongoDB 4.0 推出了更强大的功能支持,目前 4.0 第一个 RC 版本已经发布。 开始体验 MongoDB 4.0 RC:下载地址 ...

局长 ⋅ 06/05 ⋅ 0

spring-boot-starter-mongodb-pool

在日常工作中,我们通过Spring Data Mongodb来操作Mongodb数据库,在Spring Boot中只需要引入spring-boot-starter-data-mongodb即可。 很多时候我们往往需要操作多个数据库(微服务架构下一个...

尹吉欢 ⋅ 04/22 ⋅ 0

一把双刃剑:关于MongoDB的学习和避坑

  【IT168 评论】MongoDB 是一把双刃剑,它对数据结构的要求并不高。数据通过key-value的形式存储,而value的值可以是字符串,也可以是文档。所以我们在使用的过程中非常方便。正是这种方便...

博客园 ⋅ 05/28 ⋅ 0

Spring boot中mongodb的使用

mongodb的增删改查 Spring Boot对各种流行的数据源都进行了封装,当然也包括了mongodb,下面给大家介绍如何在spring boot中使用mongodb: 1、pom包配置 pom包里面添加spring-boot-starter-dat...

glen_xu ⋅ 06/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JavaScript零基础入门——(十一)JavaScript的DOM操作

JavaScript零基础入门——(十一)JavaScript的DOM操作 大家好,欢迎回到我们的JavaScript零基础入门。最近有些同学问我说,我讲的的比书上的精简不少。其实呢,我主要讲的是我在开发中经常会...

JandenMa ⋅ 25分钟前 ⋅ 0

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 52分钟前 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 59分钟前 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 今天 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 今天 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

容器之查看minikue的environment——minikube的环境信息

执行如下命令 mjduan@mjduandeMacBook-Pro:~/Docker % minikube docker-envexport DOCKER_TLS_VERIFY="1"export DOCKER_HOST="tcp://192.168.99.100:2376"export DOCKER_CERT_PATH="/U......

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部