一、 前言
MongoDB是一种流行的数据库,可以在不受任何表格Schema模式的约束下工作。数据以类似JSON的格式存储,并且可以包含不同类型的数据结构。但为了能够充分利用MongoDB的优势,您必须了解并遵循一些基本的数据库设计原则。在讲解设计方法之前,我们必须首先了解MongoDB存储数据的结构。
二、SQL概念与MongoDB概念对比
数据结构对于一个软件来说是至关重要的,MongoDB 在概念模型上参考了 SQL数据库,但并非完全相同。
2.1 数据如何存储在MongoDB中
与传统的RDBMS关系型数据库不同,MongoDB并没有表Table,行row和列column的概念。它将数据存储在集合collections,文档documents和字段fields中。下图说明了与RDBMS类比的结构之间的关系:
SQL概念 | MongoDB概念 | 说明 |
database | database | database 数据库,与SQL的数据库(database)概念相同,一个数据库包含多个集合(表) |
table | collection | collection 集合,相当于SQL中的表(table),一个集合可以存放多个文档(行)。 不同之处就在于集合的结构- (schema)是动态的,不需要预先声明一个严格的表结构。更重要的是,默认情况下 MongoDB 并不会对写入的数据做任何schema的校验。 |
row | document | document 文档,相当于SQL中的行(row),一个文档由多个字段(列)组成,并采用bson(json)格式表示。 |
column | field | field 字段,相当于SQL中的列(column),相比普通column的差别在于field的类型可以更加灵活,比如支持嵌套的文档、数组。 |
此外,MongoDB中字段的类型是固定的、区分大小写、并且文档中的字段也是有序的。
2.2 SQL对应关系
SQL概念 | MongoDB概念 | 说明 |
primary key | _id | _id 主键,MongoDB 默认使用一个_id 字段来保证文档的唯一性。 |
foreign key | reference | 引用,勉强可以对应于 外键(foreign key) 的概念,之所以是勉强是因为 reference 并没有实现任何外键的约束,而只是由客户端(driver)自动进行关联查询、转换的一个特殊类型。 |
view | view | view 视图,MongoDB 3.4 开始支持视图,和 SQL 的视图没有什么差异,视图是基于表/集合之上进行动态查询的一层对象,可以是虚拟的,也可以是物理的(物化视图)。 |
index | index | index 索引,与SQL 的索引相同。 |
join | $lookup | $lookup,这是一个聚合操作符,可以用于实现类似 SQL-join 连接的功能 |
transaction | transaction | transaction 事务,从 MongoDB 4.0 版本开始,提供了对于事务的支持 |
group by | aggregation | aggregation 聚合,MongoDB 提供了强大的聚合计算框架,group by 是其中的一类聚合操作。 |
三、BSON 数据类型
MongoDB 文档可以使用 Javascript 对象表示,从格式上讲,是基于 JSON 的。但是 JSON 也有自己的短板,比如无法支持像日期这样的特定数据类型,因此 MongoDB 实际上使用的是一种扩展式的JSON,叫 BSON(Binary JSON)。
BSON 所支持的数据类型包括:
四、 数据库设计技巧和窍门
4.1 规范化存储与非规范化存储
因为MongoDB使用文档来存储数据,所以理解“规范化存储“”和“非规范化存储”的概念非常重要。
规范化存储:-规范化意味着将数据存储到多个集合collections中,并在它们之间设计关联关系。数据保存之后,更新数据比较容易。但是在读取数据的时候,规范化存储的缺点就显现出来。如果要从多个集合collections查找数据,则必须执行多个查询,从而使读取数据的速度变慢。 (比如:将网页标题、作者、内容分别存储到不同的collections中)
非规范化存储:-这种方式将若干对象数据,以嵌套的方式存储到单个文档中。它在读取数据的时候表现更好,但在写入时会变慢。这种存储数据的方式还将占用更多空间。 (比如:将网页标题、作者、内容分别存储到同一个collection中)
所以在两种存储数据方式之间进行选择之前,先评估一下你的应用数据库的使用方式。 如果您有一个不需要频繁更新的数据,更新的即时一致性不是很重要,但是在读取时需要良好的性能,那么非规范化可能是明智的选择。(比如:我们博客的博文,作者一旦保存之后,几乎就不在进行频繁的修改,但是面临着读者频繁的读取阅读操作)
如果数据库中的文档数据需要不断的更新,并且您希望在写入时具有良好的性能,那么您可能需要考虑规范化存储。(比如:需要频繁修改数据的业务类系统)