注:本案例来自mongodb官方教程ppt,也是一个非常典型的case,故此翻译,并结合当前mongodb版本做了一些内容上的更新。
本案例非常适合与iot场景的数据采集,结合mongodb的sharding能力,文档数据结构等优点,可以非常好的解决物联网使用场景。
案例背景是来自真实的业务,美国州际公路的流量统计。数据库需要提供的能力:
存储事件数据
提供分析查询能力
理想的平衡点:
内存使用
写入性能
读取分析性能
可以部署在常见的硬件平台上
非常“传统”的设计思路,每个事件都会写入一条同样的信息。多少的信息,就有多少条数据,数据量增长非常快。
数据采集操作全部是insert语句;
对每分钟的平均速度计算非常友好(speed_sum/speed_num);
数据采集操作基本是update语句;
数据精度降为一分钟;
每秒的数据都存储在一个文档中;
相比上面的方案更进一步,从分钟到小时:
每小时的数据都存储在一个文档中;
更新最后一个时间点(第3599秒),需要3599次迭代(虽然是在同一个文档中)
进一步优化下:
用了嵌套的手法把秒级别的数据存储在小时数据里;
更新最后一个时间点(第3599秒),需要59+59次迭代;
嵌套结构正是mongodb的魅力所在,稍动脑筋把一维拆成二维,大幅度减少了迭代次数;
从写入上看:后者每次修改的数据量要小很多,并且在wiredtiger引擎下,同一个文档的修改一定时间窗口下是可以在内存中合并的;
从读取上看:查询一个小时的数据,前者需要返回3600个文档,而后者只需要返回60个文档,效率上的差异显而易见;
从索引上看:同样,因为稳定数量的大幅度减少,索引尺寸也是同比例降低的,并且segid,ts这样的冗余数据也会减少冗余。容量的降低意味着内存命中率的上升,也就是性能的提高;
从写入上看:因为wiredtiger是每分钟进行一次刷盘,所以每小时一个文档的方案,在这一个小时内要被反复的load到pagecache中,再刷盘;所以,综合来看后者相对更合理;
从读取上看:前者的数据信息量较大,正常的业务请求未必需要这么多的数据,有很大一部分是浪费的;
从索引上看:前者的索引更小,内存利用率更高;
那么到底选择哪个方案更合理呢?从理论分析上可以看出,不管是小时存储,还是分钟存储,都是利用了mongodb的信息聚合的能力。
每小时的信息用一个独立的文档存储:设计上较极端,优势劣势都很明显;
每分钟的信息用一个独立的文档存储:设计上较平衡,不会与业务期望偏差较大;
落实到现实的业务上,哪种是最优的?最好的解决方案就是根据自己的业务情况进行性能测试,以上的分析只是“理论”基础,给出“实践”的方向,但千万不可以此论断。
说到时序存储需求,大家一定还会想到非常厉害的influxdb,influxdb针对时序数据做了很多特定的优化,但mongodb采用聚合设计模式同样也可以大幅度较少数据尺寸。根据最新的测试报告,读取性能基本相当,压缩能力上influxdb领先mongodb。但mongodb的优势在于可以存储更丰富的信息,比如地理坐标,文本描述等等其他属性,业务场景上支持更广泛。
另外,mongodb的sharding水平扩展能力,aggragation功能,spark connector等等特性,对iot来说,生态优势明显。