最近,公司一项目实施需要对MongoDB数据库的顺序读性能进行评估测试,已备项目实施提供决策依据。
问题:主单对应的明细表关系,每一条主单在明细表中都有大量的明细存在,而明细单独以单个文档存储在mongodb中会因为key-value关系浪费大量的key值空间。
解放方法:将明细表中的同一主单对应的明细压缩到一个文档中,提取冗余字段属性,将明细特有key-value组织成一个数组,这样数据相对集中,可以提高mongodb的顺序读性能。
前提:主单对应的明细条数不能过多,压缩汇聚的明细总体积不能超过当前mongodb支持的单个文档的最大体积,具体看数据库配置,有的限制是16MB,有的32MB,有的是64MB;我们的库最大文档支持16MB。
测试前准备:在同一个mongodb数据库中存放优化前的数据集合、优化后的数据集合,例如我们优化前的集合是bill_detail、优化后的集合是detail_coll。
测试方法:测试方法如下表格所示
[mongodb@se122 test1]$ cat bill_detail_ETL_Patient_IDStr1.sh currentTime1=`date +%Y%m%d%H%M%S` echo "start_time:" $currentTime1 mongo --port 27000 wl_insert currentTime2=`date +%Y%m%d%H%M%S` echo "finish_time:" $currentTime2 time3=$(($currentTime2 - $currentTime1)) echo "execution time_elapsed:" $time3 [mongodb@se122 test1]$ |
[mongodb@se122 test1]$ cat bill_detail_ETL_Patient_IDStr1.js var cursor = db.ETL_Patient_IDStr.find(); var i=0; while(cursor.hasNext()){ var obj = if(i<=1157){ db.bill_detail.find({"ETL_Patient_IDStr":obj.ETL_Patient_IDStr}).explain("executionStats"); } if(i>1157){ break; } i++; } [mongodb@se122 test1]$ |
测试方法说明:如表格所示,对优化前后的明细表各写四对sh和js脚本,其中每个sh单循环执行一次对应.js脚本,其中.js脚本对优化前后的集合分段执行从磁盘加载到mongo数据库内存的操作,四对sh和js脚本同时执行,将整个优化前或优化后的集合加载到服务器内存。测试前清理服务器内存及缓存,重启数据库,先测试优化后的文档detaill_coll;再清理服务器内存及缓存,重启数据库,后测试优化前的文档bill_detail。
测试总览表格:
对比 指标 |
优化前 |
优化后 |
对比度 |
期望 |
数据量 |
55357286 |
427003 |
7.70% |
减少 |
集合并行加载时间 |
932s |
432s |
46.35% |
降低 |
存储磁盘IO请求数峰值 |
3917/s |
887/s |
22.64% |
降低 |
存储磁盘IO吞吐量峰值 |
15.88MB/s |
19.38MB/s |
22.04% |
提高 |
mongo数据返回峰值 |
23.4KB/s |
52.8KB/s |
55.68% |
提高 |
mongo消耗内存 |
52.4GB |
36GB |
31.30% |
下降 |
mongo消耗缓存 |
66% |
50% |
16% |
下降 |
结合一款grafana软件,结果会更直观:
图4 优化后的读操作磁盘IO请求
图5优化前的读操作磁盘IO请求
针对图4、图5,相同查询操作测试下,优化前的物理磁盘IO请求数峰值是3917次/s,优化后的物理磁盘IO请求数峰值降低到887次/s,另外,可以看出,优化前查询操作导致磁盘IO请求居高不下。
图6 优化后的查询操作IO吞吐量
图7 优化前的查询操作IO吞吐量
针对图6、图7,相同查询操作测试下,优化前的物理磁盘IO吞吐量数峰值是15.88MB/s,优化后的物理磁盘IO请求数峰值提高到19.39MB/s,优化后顺序IO提高了磁盘IO读性能,相比优化前提高了3.5MB/s;另外,磁盘IO高峰期,优化后相比优化前在时间上有明显的缩短。
图8 优化后的mongo数据库数据返回
图9 优化前的mongo数据库数据返回
针对图8、图9,相同查询操作测试下,优化前mongo数据库数据返回数峰值是23.4kb/s,优化后的mongo数据库数据返回数峰值提升到52.8kb/s,优化后数据分布有利于数据库顺序读,明显提升了mongo数据库顺序读的性能,同时降低了mongo数据库高负载时间。
图10 优化后的mongo数据库占用主机内存
图11 优化前的mongo数据库占用主机内存
针对图10、图11,
从图10-图11,显示的数据可以看出,优化后相比优化前,mongo数据库占用的主机内存下降31.30%。
以上图表数据,除了使用grafana软件,也可以使用linux操作系统命令获得。
测试过程中,使用echo 1 > /proc/sys/vm/drop_caches命令来清空主机缓存,通过ps -ef|grep mongo来查找mongodb的数据库主进程,如下所示131351进程就是啦,使用kill -2 131351命令关闭数据库,再重启来清空数据库内存的占用。
[root@se122 ~]# ps -ef|grep mongo
mongodb 66833 1 5 Aug01 ? 13:48:42 mongos --configdb 10.117.130.121:27001 --logpath /home/mongodb/mongodata/logs/mongos.log --port 27000 --fork
root 72060 71965 0 10:58 pts/1 00:00:00 grep --color=auto mongo
root 75111 75073 0 Aug09 pts/7 00:00:00 su - mongodb
mongodb 75112 75111 0 Aug09 pts/7 00:00:00 -bash
root 107805 1 0 Aug08 ? 00:00:00 su - mongodb
mongodb 107806 107805 0 Aug08 ? 00:00:00 -bash
mongodb 107849 107806 0 Aug08 ? 00:00:01 mongo --port 27000
mongodb 131351 1 0 Aug08 ? 00:23:21 mongod --dbpath /home/mongodb/mongodata/rs1 --logpath /home/mongodb/mongodata/logs/rs1.log --port 27011 --directoryperdb --syncdelay 15 --fork
[root@se122 ~]#
[root@se121 ~]# iostat -txk 2 #使用该命令可以持续获得磁盘IO使用情况
Linux 3.10.0-327.10.1.el7.x86_64 (se121) 08/09/2016 _x86_64_ (32 CPU)
08/09/2016 10:03:01 AM
avg-cpu: %user %nice %system %iowait %steal %idle
0.67 0.00 0.63 0.03 0.00 98.67
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 0.00 46.50 12.50 1170.00 98.25 42.99 0.18 3.03 3.83 0.04 0.56 3.30
dm-0 0.00 0.00 12.00 10.50 764.00 93.25 76.20 0.02 0.78 1.42 0.05 0.76 1.70
dm-1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-2 0.00 0.00 35.00 2.00 412.00 5.00 22.54 0.16 4.34 4.59 0.00 0.45 1.65
dm-3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
08/09/2016 10:03:03 AM
avg-cpu: %user %nice %system %iowait %steal %idle
0.81 0.00 0.49 1.17 0.00 97.53
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 2.50 966.50 28.00 6724.00 138.75 13.80 1.28 1.29 1.33 0.00 0.93 92.95
dm-0 0.00 0.00 241.50 17.00 3672.00 79.00 29.02 0.38 1.46 1.56 0.00 1.30 33.70
dm-1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-2 0.00 0.00 725.00 13.50 3048.00 59.75 8.42 0.91 1.23 1.25 0.00 1.22 90.20
dm-3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
08/09/2016 10:03:05 AM
avg-cpu: %user %nice %system %iowait %steal %idle
0.30 0.00 0.23 0.09 0.00 99.37
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 0.00 809.00 2.50 3312.50 7.00 8.18 0.88 1.09 1.09 0.20 1.08 87.70
dm-0 0.00 0.00 4.50 0.50 18.50 2.00 8.20 0.01 1.10 1.22 0.00 0.60 0.30
dm-1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
dm-2 0.00 0.00 804.50 2.00 3294.00 5.00 8.18 0.88 1.09 1.09 0.25 1.09 88.20
dm-3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
[BEGIN] 2016/8/9 10:06:26
free -s 10 -m 10 #使用该命令可以持续获得主机内存、缓存的使用数据
total used free shared buff/cache available
Mem: 128662 15784 110015 137 2862 112370
Swap: 4095 28 4067
total used free shared buff/cache available
Mem: 128662 16595 109069 137 2998 111560
Swap: 4095 28 4067
。
。
。
total used free shared buff/cache available
Mem: 128662 49774 70199 137 8689 78381
Swap: 4095 28 4067
经过单位换算后,就可以完成测试总览表格了。
总结,文档聚合优化,使得数据相对集中,有利于mongodb的顺序读,对于需要mongodb短时间内加载大量数据到内存或获取到应用服务器是有利的。
声明:实验过程、结果及对mongodb认识,如果有不妥的地方,我接受批评指正。