今天一早就收到一封关于 MongoDB 的邮件,MongoDB began trading as a public company on the NASDAQ under the symbol “MDB.”。是的,在经过长达 10 多年的开发应用后,MongoDB 终于登上了纳斯达克。作为一个 MongoDB 的忠实粉丝,除了为它感到骄傲之外,还想在此整理一下最近工作中在 MongoDB 上的一些想法和经验。此文也算是为 MongoDB 的推广献一份力量。
准备工作关系型数据库已经统治数据存储长达三十几年的时间,即便在 2000 年以后诞生了 NoSQL 数据库,但他的出现并没有改变关系型数据的统治地位。随着最近几年互联网应用的快速崛起,以及互联网用户的不断增加,数据来源越来越复杂多样,传统关系型数据存储面临了很大的挑战。这种挑战体现在数据格式死板,改动困难,存储不够灵活,难于扩展等方面。因此,很多企业、公司都先后把数据从关系型迁移到 NoSQL 上来,其中 MongoDB 又是使用相对较广泛的数据库实现。本文就为大家分享一下关系型数据导入进 MongoDB 中应当遵循的步骤和注意的问题。
在考虑将关系型数据导入到 NoSQL 中时,首先需要确认的几点是:这个导入过程不会是全自动的,并不是像备份数据,迁移数据,记住几个命令那么简单;其次,这个过程不是一个纯技术问题,在制定具体方案时,项目经理,业务分析人员,开发人员,数据库管理员都应当参与到方案的讨论中。迁移的计划、技术方案、各个项目负责人的职责应当在全体人员在场的情况下制定清楚;最后,应当考虑到迁移失败以后的恢复方案,根据应用数据的复杂程度不同,迁移的工作量也不会完全一样。
上图列出了一个项目经过关系型数据向 NoSQL 中迁移的大致步骤,当然这绝对不是一个唯一的标准。只是通常情况下的做法,可能会根据不同项目的特别需求有一些调整。下面我们来详细分析每一个阶段的具体工作内容。
数据模型定义有可能你会觉得奇怪,MongoDB 不是结构无关的 NoSQL 数据库吗?为什么我们要提到数据库表结构定义。实际上,NoSQL 中的结构是指从技术层面来讲,数据库对表结构没有强约束,任何格式的 JSON 都可以插入进 MongoDB 表中。但是,我们在做项目时不能为所欲为的在数据库中插入数据,一定要遵循我们自己定义的一套规则来进行,否则程序根本无法管理数据层面的业务逻辑。在讨论表结构之前,先来看一下 MongoDB 中的一些术语和关系型数据库的对应关系。
看起来很好理解,在 MongoDB 中我们把表称做Collection,表中每一行的数据称作Document。其他的基本沿用关系型数据库的命名。在 MongoDB 中,所有的数据格式都是以 JSON 为数据库类型,它能够比较灵活的存储各种数据库关系。这也是为什么 MongoDB 能够在一个 Collection 中存储各种不同结构的数据。比如,你可以插入这样一个 JSON 到 MongoDB 中:{"user": {"name": "Zhang San", }},另外再插入这个 JSON{"product": {"id": "00001"}}。可以看到这两个 JSON 没有任何关系,也没有任何相同的属性,但在 MongoDB 中都是合法的数据,他们可以同时存在于一个 Collection 中。当然,我们并不鼓励大家这样做,因为这样很难维护你的数据库表格,而且对于查询索引来说也很麻烦,会产生很多不必要的索引存储。我们所说的结构灵活指的是在一个结构框架基础上,可以灵活扩充、添加新的数据而不用重新定义数据 Schema。因此,我们在进行数据库迁移之前需要讨论如何定义 Collection 的结构。
MongoDB 将 JSON 存储成一个叫BSON的数据结构中,BSON指的是Binary JSON,二进制 JSON,并在 JSON 的基础上添加了一些新的数据类型,int,float,long。JSON 格式可以灵活的存储嵌入式数据结构,以及数组,要是在关系型数据库中实现其难度是很难想象的。在定义Collection 结构时,需要根据应用程序实际需求找出数据模型的定义,最大程度的利用 MongDB 的存储灵活性。例如,下面是一个典型的两张一对多的数据库表格。
学生表:
成绩表:
其中,第一张表是学生表,第二张是学生成绩表,一个学生可以有多门课程的成绩,因此他们之间是一对多的关系,其中studnet_id在学生表中是主键,对应成绩表中的外键。在关系型数据库中这种表示方法完美并正确,但是到了 MongoDB 中也许就是另外一种存储样式了。为了充分利用 JSON 格式的内嵌式存储,我们通常会把这种关系存储到 Collection 中的一条记录(Document),如下所示: