任明飞 李学军 崔蒙蒙 杨双龙 孙小奇
摘要:随着社会的发展和软件技术的不断进步,互联网的数据量也呈现出爆炸型增长,此外数据的类型也变得更加多样,传统的关系型数据库在对海量级的数据和多种类型的非结构化数据的处理上已经无法满足开发人员的需求,NoSQL即非关系型数据库凭借本身的优势得到了迅速发展,其中MongoDB就是一个基于分布式,文件存储的NoSQL数据库。该项目通过基于MongoDB的非关系型数据库的设计与开发,展示了非关系型数据库和传统的关系型数据库的区别以及MongoDB的主要技术和使用方式。
关键词:关系型数据库;非关系型数据库;MongoDB;分布式;文件存储
中图分类号:TP311
文献标识码:A
文章编号:1009-3044(2019)34-0001-02
1 MongoDB概述
MongoDB是一个基于分布式,文件存储的非关系型数据库,其特点是高性能、易部署、易使用,存储数据方便。 不同于传统关系型数据库将数据以表的形式进行存储,在MongoDB中数据是以文档的形式进行存储。文档为BSON格式,其内部可以包含多种类型的文件、数据也可以内嵌别的文档,模式十分白由。MongoDB也被称作非关系型数据库当中最像关系数据库的,是一个介于关系数据库和非关系数据库之间的产品,其功能也是众多非关系数据库当中最丰富的。
MongoDB在存储上的高拓展性使得其在面对海量级数据时比其他的数据库更加具备优势,其数据模型自由可变,存储内容可按照需求随意拓展,所以也适用于一些新应用,需求容易改变,数据模型无法确定,或者想快速迭代开发的产品。由于其高效的实时插入、更新与查询性能,并具备网站实时数据存储所需的复制及高度伸缩性。因此适用于常见的游戏场景、物流场景和物联网场景等。
MongoDB作为一个非关系型数据库也有一些局限性。MongoDB事务仅支持限于本机的单文档事务,某些需要参与远程事务,或者需要跨表,跨文档原子性更新的高事务性应用不建议使用,另外MongoDB目前并不支持jom操作,需要复杂查询的应用也不建议使用。
2 MongoDB文档模式设计
MongoDB的文档数据以BSON(JSON格式的一种拓展)格式存储,可以存储列表、key-value以及层次结构更加复杂的文档。由于文档存储的灵活性和复杂性导致开发者在自由组织文档结构的同时必然会面对应用层查询困难的问题,因此基于Mon-goDB的非关系型数据库在设计阶段对文档模式的设计尤为重要。
2.1 数据对象分析
本次开发的实例项目为旅游类内容管理网站项目,主要涉及的数据对象有景点数据对象,评论数据对象以及旅游攻略数据对象。
景点数据对象包含景点的图文介绍,基本信息,位置信息,评论等。旅游攻略數据对象包含旅游攻略的发布者信息,内容信息,点赞评论或者转发信息等。评论数据对象包含评论者信息,内容信息和点赞信息等。
结合实际应用场景分析,每个景点都有各自的基本信息以及游客们的评论信息,一个景点可以有多条评论,因此景点数据对象和评论数据对象之间是一对多的关系,其他同理可得数据对象关系如图1所示。
2.2 关系模型和文档模型对比
结合项目中主要的数据对象进行分析。从数据存储的角度来讲:
关系型数据库在设计时必须满足范式的要求,即关系型数据库在定义表结构时要求每一个单元格的数据必须为不可再分割的原子项。使用关系型数据库对旅游攻略数据对象进行存储至少需要建立四张表。分别是文章表、评论表、点赞表、附件表,其中评论表、点赞表和附件表都持有文章表主键。形成主外键关系。显然,数据更加复杂的景点数据对象以及数量庞大的评论数据对象都不是一张表就可以实现存储的。并且这些数据模型各自之间还存在对应关系,也需要使用外键进行关联。关系型数据库光是在数据的存储上就十分困难。
集合就是MongoDB文档组,其文档下的属性可以是一个数据项、一个对象或者是一个数组。在使用MongoDB处理旅游攻略数据对象时,只需要一个旅游攻略数据对象的文档集合就可以,文档内部包括,文章内容属性,文章发表时间属性,文件状态属性,评论数组属性,点赞数组属性,文章附件数组属性等其他信息。对于其他数据对象可以采取相同操作,文档包含的都是以bson格式存储的不同数据对象,由于bson数据便于解析,而且可以存储多种类型的数据内容,使得MongoDB的存储效率极高。
从应用层面来讲:对需求进行提升,需要在文章列表中就展示文章内容、评论、附件和点赞信息。使用关系型数据库就需要先从文章表中查询出文章列表,再根据每一个文章的主键到其他表中获取信息。如果列表要求显示10条记录,就需要执行11次的sql语句。而在这样的需求下,mongoDB仍然是只需要执行一次查询就可以获取到全部数据。
2.3 文档模式设计
MongoDB可以将模式设计划分为内嵌模式(Embedded)和引用模式(References)。
内嵌模式适合数据对象之间的关系是一对一或一对多的。但其局限性在于MongoDB的文档最大16M,面对大数组性能欠佳。在开发过程中,如果数据对象模型数量不多,关系结构不复杂。这种情况下选择内嵌模式,可能一种对象只需要对应一个集合即可。由于内嵌模式的局限性。内嵌的数组过大时,例如一个明星的博客可能有几十万或者几百万的回复,这个时候如果把回复内容放到一个数组里,可能会超出16M的限制。这个时候就应该考虑使用引用方式。
引用模式适合多对多的关系,并且两个对象都是主要对象。它的局限性在于查询和写入数据需要多次查询、写入,并且不支持跨表事务性。实现方式是不同的数据对象建立两个集合,通过在集合中存储其他对象的ID值实现关联,这种方式和关系型数据库十分相似,从查询操上讲,可能需要两次以上才能把需要的数据取回来。另外现阶段MongoDB并不支持跨表的事务性,所以对于强事务的应用场景应当慎用引用模式。
开发过程中完全依靠数据对象关系并不能完美解决选择内嵌还是引用的问题,在这些时候就需要了解MongoDB的文档模式设计的设计原则:MongoDB的设计是为应用程序服务,而并非为了存储的优化。设计MongoDB的目的是为了实现应用程序的最佳性能。这些和关系型数据库设计的原则有很大不同,为了达到性能的优化可能需要去做一些反范式的内容。因此MongoDB文档设计模式的选择除了考虑数据本身的特点之外还应当考虑应用层面对数据的操作。
3 MongoDB文档模式实现
通过上文的分析,对项目中的数据对象进行文档设计和实现,景点数据对象由于自身结构复杂,内容图片以及附加信息过多,自身数据大小远大于评论数据对象和旅游攻略数据对象,因此在景点数据对象和其他两个数据对象之间的模式选择引用模式,两种数据之间的联系则通过数据对象中的标识ID进行联系。旅游攻略数据对象和评论数据对象之间选择的是内嵌模式。由于采用引用模式的文档模型在逻辑上和关系型数据库十分相似,本文不再赘述,主要分析使用内嵌模式的旅游攻略数据对象的文档模式实现。
对數据文档模式的设计和实现时应当结合数据自身特点和其在应用层面的操作共同考虑。分析实际应用场景中旅游攻略展示的效果除了文章本身的内容,还应当包含点赞列表。点赞用户的头像、昵称;以及评论列表,评论内容,评论用户的头像、呢称等。结合上文,对旅游攻略数据对象和评论点赞数据对象之间采取的是内嵌模式。故而我们在文档设计模式上首先构建了旅游攻略数据对象,在旅游攻略数据对象内部嵌套了多个包含评论内容,用户以及图片文字等信息的评论数据对象。
对以上文档模型进行分析,该文档设计模式中在景点对象内嵌了所有的点赞对象和评论对象,结合需求分析同时也需要在用户对象中内嵌相应的评论和点赞对象,在MongoDB这种文档型数据库选择这种设计是没有必要的,反而造成了大量的数据冗余。另一个问题是在上述的设计里存储用户评论内容的图片或者头像等URL也占据了大量的空间,实际情况是,评论用户数据的URL相对来说是全局稳定的,基本不会发生变化。
根据以上几个问题,我们重新优化了文档模型的设计,在对象内部嵌套comment_obj_id与praise_obj_idj两个字段,用以存储两个对象的id。文档数据内部的URL、username信息全部移除,因为对需求进行分析可以发现,业务抽象上来说URL、username这类信息实际上是非常稳定的,不会发生特别大的频繁变化。并且这两类信息实际上都应该是跟uid绑定的,每个uid含有指定的URL.username。是最简单的keV-value模型。所以,这类信息可以通过一层缓存加速读取查询。
对比可以发现,优化后的结构要比优化前小了几个数量级。虽然两者都满足MongoDB文档模式设计的要求规范,但是后者在存储空间占用以及查询的性能上都远优于前者。
4 总结
通过本次MongoDB数据库的设计与开发,体现了MongoDB在数据存储,检索上的强大优势,以及MongoDB在复杂数据以及海量数据存储方面远超传统关系型数据库的优异性能。MongoDB的文档模型设计自由,但绝对不是等同于关系型数据库的粗暴聚合,并且当前的MongoDB还存在一定的局限性,因此在设计阶段,还需要结合实际需求和业务,进行合理的设计。
参考文献:
[1] Peter Bakkum(美).MongoDB实战[M].徐雷,译.华中科技大学出版社,2017.
[2] KristinaChodorow(美)等.MongoDB权威指南[M].程显峰,译.人民邮电出版社,2011.
[3]王光磊.MongoDB数据库的应用研究和方案优化[J].中国科技信息,2011.
【通联编辑:代影】
收稿日期:2019-08-28
作者简介:任明飞(1996-),男,河南焦作人,河南科技大学本科在读,研究方向为非关系型数据库、数据库分布式部署。