3.1.3 MongoDB

除了HBase这样的列式存储,NoSQL的数据库中还有一部分采用的是文档型存储,MongoDB就是其中的一个典型代表。MongoDB(https://www.mongodb.org/)是基于分布式文件存储的数据库,最新版本已经超过3.0,由C++语言编写,其目标是为Web应用提供可扩展的高性能数据存储。它的主要功能特性为面向集合存储,且拥有自由的Schema模式定义方式。所谓的“面向集合”,意思是数据被分组存储在数据集中,该数据集称为一个集合(Collection)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库里的表,不同的是Schema模式的定义。与HBase类似,MongoDB并没有关系型数据库那样的关系模型,也没有很严格的Schema模式和数据一致性的限制,而是提供了更为灵活的数据格式和扩展能力。这意味着对于存储在MongoDB数据库中的文件来说,使用者不一定要知道它的结构定义,甚至还可以将不同结构的文件存储在同一个数据库里。不过,MongoDB和HBase也存在差异,具体差异如下。

  • 底层的支持:HBase是架构在HDFS之上的,它会将数据按照列拆分开来存储,对MapReduceHadoop MapReduce的内容会在第4章数据处理中做具体介绍。支持得非常好。而MongoDB则会直接将整个数据存储在文件系统之上,与HDFS没有关联。MongoDB的底层也存在大型文件存储的概念,称为GridFS。不过GridFS只是一个规范,具体的内容还是通过MongoDB来实现的。
  • 数据模型:HBase的数据模型和关系型的二维表非常相似,其灵活性体现在列式存储上,它对列(或者说属性、字段)的定义没有严格要求,而且可以通过超多的列族来构建一个超宽的表格,代替关系型数据库中的Join等复杂操作。而MongoDB的数据模型是以文档为基本单位的,其灵活性体现在文档可以支持多种复杂的结构。在IT领域,“文档”本身就是一个宽泛的概念,在本书中也会多次提及(在第5章的信息检索部分还会提及,基本概念相当,但是具体内容和此处稍有不同)。这里的文档可以简单地理解为一堆属性或字段的集合,与二维表中的行相对应,不过最大的区别在于,MongoDB文档中的属性或字段并不局限于特定的类型,如第一篇文档的“俱乐部”属性可以是一个字符串,而第二篇文档的“俱乐部”属性就变成了一个新的复合对象,包括俱乐部的名称、成立时间、负责人等。这在关系型数据库中一般都是通过Join来实现的,而HBase需要做的就是将嵌套的内容转化成扁平的列族。图3-8展示了关系型数据表、HBase的宽表和MongoDB文档表的对比情况。
  • 对数据的拆分:HBase将列族进行拆分,分布在HDFS的不同资源节点上。MongoDB的设计者可能考虑到了嵌入多级文档的复杂性,对文档的大小做了限制,而且不会将单个文档的数据再进行切分和分布式存储,这点更接近行式存储。不过,文档的灵活定义仍然保证了对非关系型数据的支持。

图3-8 关系表、HBase和MongoDB的数据模型对比

除了面向文档和模式更灵活,MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系型数据库单表查询的绝大部分功能,而且还支持对任意字段的数据建立多级索引(还包括基于地理空间的索引),能够大幅地提升处理效率。当然,即使没有架构于HDFS和Hadoop生态之上,MongoDB仍然提供了良好的并行处理和高扩展性,支持数据的复制和恢复,实现了故障恢复等功能。