型号:Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10Ghz
主频:2.1Ghz
核心:4(处理器)
型号:LSI MRSASRoMB-8i SCSI Disk Device
容量: 2T
容量:32G
操作系统使用 Redhat Sever6.4-X86-64。
文件系统使用EXT4。
Mongodb 2.6.5-X86-64
数据行数:10亿行。
存储大小:219.847GB
数据文件存储方式:第一个文件65M,第二个文件129M,第三个文件257M,第四个文件512M,第五个文件1.1GB,其后均为2.0GB。
数据格式:共四列,第一列为状态量ID(1-5000) ,第二列为状态值(0-150),第三列为状态量产生时间(20090101开始),第四列为插入数据库的时间戳。
1、并发与插入测试:在进行插入性能测试时考虑到并发情况与插入情况,采用Mongodb的Nodejs客户端进行并发插入性能测试。
2、查询性能测试:在进行查询性能测试时使用Mongodb的Explain语句进行执行计划的查询,该语句类似于Oracle的Autotrace功能。
为测试Mongodb在亿级数据的实时查询性能,以“Jsp+Servlet+Jquery+D3Js”做了一个实时查询的功能,该功能每秒刷新一次页面实时展示从Mongodb中查询到的数据。
测试插入性能时,考虑到可能要在建立索引之后进行插入操作,所以插入性能测试分为“索引建立之前”与“索引建立之后”的查询操作。
考虑到单进程与并发进程的情况,分为“单进程插入测试”与“10并发插入测试”。
关于索引的创建,以下有两点说明。
第一,只以查询字段创建单索引。
第二,在创建索引时,测试表已有约5亿数据量。
测试查询性能时,需要考虑到索引建立前后查询性能的差别,以及返回数据量对响应时间的影响,判断它们之间是否有一定的关系,所以测试条目以返回的数据量分“单条数据”、“万级数据”、“百万级数据”和“千万级数据”。
在测试万级以上的返回时间时,只测试索引建立之后的情况,因为影响时间实在太长,等不得。
在测试查询性能时要考虑到聚合查询的情况,聚合查询以数据量分“万级数据”、“百万级”和“千万级”,只以一个字段为聚合条件,并且只做“Count”运算,在Mongodb中做聚合操作使用类似以下语句:
db.runCommand(
{
"group":
{
"ns":"visonLog",
"key":{"value":true},
"initial":{"count":0},
"$reduce":function(doc,prev)
{
prev.count++;
},
"condition":{"time":{"$gt":"20090101130101000",
"$lt":"20090101140101000"}}
}
}
);
插入性能统计表格1
统计项目 |
单进程插入(索引建立前) |
单进程插入(索引建立之后) |
统计结果 |
656/s - 746/s |
534/s - 712/s |
插入性能统计表格2
统计项目 |
10进程并发插入(索引建立前) |
10进程并发插入(索引建立之后) |
统计结果 |
3817/s - 3964/s |
3306/s - 3389/s |
查询性能统计表格1
统计项目 |
单条数据响应时间(索引建立之前) |
单条数据响应时间(索引建立之后) |
统计结果 |
1268904/ms |
15/ms |
查询性能统计表格2
统计项目 |
返回万级数据 |
返回百万级数据 |
返回千万级数据 |
统计结果 |
20/ms |
8868/ms |
217755/ms |
查询性能统计表格3
统计项目 |
万级数据聚合 |
百万级数据聚合 |
返回千万级数据 |
统计结果 |
9329/ms |
542756/ms |
1899415/ms |
在测试中观察到几个情况,这些情况有好有坏:
第一,在创建索引时,其它的操作如“showcollections”、“db.table.find()”等操作均处于等待状态。
第二,内存占用量大,当前库的大小达到内存大小(测试环境是32G)时,内存占用达到95%。查资料得知Mongodb在分配内存时是把整个库文件映射到内存中,那就意味着Mongodb在多数的情况下会内存用尽,在该情况下Mongodb的插入性能将会受到影响。
第三,索引建立时间过长,在该测试环境下5亿数据大约用时1.5小时。这个时间远长于Oracle的时间。
第四,Mongodb在达到亿级之后,查询性能与数据总量的大小看不出太大的区别,从这个意义上来讲,Mongodb对大数据量的查询是较好的选择。
第五,Mongodb的存储是以多个文件
一、并发插入性能:
从插入性能的测试数据来看, 插入性能在索引建立前后并没有大幅度的落差 , 索引建立之后依然可以达到600-700的插入速度。
在并发的情况下,可以看到性能的下降,每秒少插入大约500条数据,但是插入速度比较稳定,未有太大的幅度。
二、查询性能:
建立索引之后,查询速度卓越,从5亿数据中返回万级数据响应速度也可以达到几十毫秒,那么1秒刷新一次也是可以的。
但mongodb不适合聚合操作,上例中查询出1万条数据以一个字段做聚合,时间是9秒,100万数据用时达到将近10分钟,以我个人使用Oracle的经验来说,这个性能是要低于Oracle的。
三、最终总结:
Mongodb适合做实时监控数据,在5亿条数据中返回1万条数据只用几十毫秒,实时监控时就可以把每秒的监控数据返回到前台,达到1秒刷新一次页面的目的。
但是Mongodb不适合做数据仓库,并且对于聚合操作较多的统计分析场景也不适用,甚至对Mongodb数据库的ETL操作也要精心设计它的数据才能被纳入数据仓库中。
并且Mongodb的内存管理使用了“内存映射存储引擎”,简单说来就是把库文件整个的映射到内存中,那就意味着如果文件大于内存的话,服务器的内存将几乎全部被占用掉,这个问题几乎没有本质的解决办法,所以使用时一定要考虑使用场景。