0%

关系型数据库和非关系型数据库

非关系型数据库

来自Mongodb开发者的话,出自知乎

「让开发者更高效」概括了 MongoDB 相较于关系型数据库带来的全部价值。这要放在最近十年整个行业的大背景下理解。软件行业的工资水平是出了名得高。这意味着软件开发的成本中,人力成本已经超越了硬件成本,成为成本里的大头。曾经长周期、瀑布式的开发流程被强调快速迭代的开发流程所替代。所有这些,加上你经常听说的热词,比如敏捷开发,微服务,DevOps,都指向「让开发者更高效」。这一背景下,基于关系表的关系型的数据模式也被灵活的非关系型数据模式替代。

使用文档模型

文档模型与面向对象的数据表达方式更相似更自然。与关系型数据库中表结构不同,文档中可任意嵌入数组和子文档,就像程序中的数组和成员变量一样。这是关系型数据库三范式不允许的。但实际中我们经常看到一对多和一对一的数据。比如,一篇博客文章的 Tag 列表作为文章的一部分非常直观,而把 Tag 与文章的从属关系单独建立一张关系表就不那么自然。再比如,一个订单下面的收货地址,包括省、市、区、街道和门牌,作为一个子文档,与订单的信用卡地址很容易区分开。更方便的是,嵌入的数组和子文档之上可以直接建立索引,比如我可以很快找到所有 Tag 包含 MongoDB 的文章。

性能

在关系数据库中,为了满足一个查询,多个表的数据都要参与 Join,每一个表都对应着磁盘的一次读取。这和数据放在一个地方,一次读完,当然完全不同。更简单的数据访问模式也让开发者更容易理解数据库的性能表现,尤其是当涉及到索引时。

灵活

关系数据库,常见的运维问题是给已有数据加一个新的属性,从数据表到应用数据层都要改。尽管有些工具可以把它自动化,这仍然是一个复杂的工作,尤其是更新产品线上数据库的时候。MongoDB 没有定义 Schema(模式)的话,就不需要改动数据库,只需要在应用层做必要的改动。

另一个问题是,纯粹业务需要的自定义属性,如不同商品的各种特性,我能理解的是在商品筛选的时候,这些特性可能临时成为区分用的指标,产品这个表应该怎么设计?最简单的方案,是把每个可能的属性都变成单独一列,当然这个方案不能扩展。另一个例子,一个通讯录允许用户随意添加新的联系方式,你有 Facebook,他有 Twitter。一种方案是在程序里把所有自定义属性序列化,比如用 JSON 放到同一字段里。另一种方案,叫做 Entity-attribute-value Model,把自定义属性和他们的数据类型,进一步抽象,增加关系表来表现。这时,相比这些复杂方案,MongoDB 没有 Schema 的优点就显现出来了。

扩展

数据一台机器放不下了,就需要 sharding(分片)把它放到几台机器上去。分片是 MongoDB 多年以来的原生功能,与 MongoDB 其他功能高效整合。例如,分片集群中一个复杂的聚合查询会自动地根据 Shard Key(片键)分配到多个结点上运行,尽可能将计算任务下推到数据结点上,最后在一个结点上聚合所有结点的结果。分片还可以在各个结点间自动迁移数据,均衡其数据量。

为了升级数据库容量,相较于关系型数据库分库分表需要同时改动应用和数据库,MongoDB分片的运维也简单很多,能够做到对应用透明。

我们希望即使机器硬件有问题,数据也不要丢,服务不受影响。分片后机器更多,任一机器出问题的概率也就更高。Replication 复制解决了这个问题。它把同一份数据实时地复制到多个结点,自动地在其中切换。MongoDB 的商业客户中,不论规模大小,使用复制集已经成了一个标准,因为数据丢失的代价远大于冗余机器的成本。

关系型数据库

第一范式

实体中的某个属性不能有多个值或者不能有重复的属性。即要求数据库表的无重复列,同一列不能有多个值。

如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的多个属性构成,新实体与原实体之间为一对多关系

第二范式

非主属性完全依赖于主关键字。
经典的例子是考察一个学生在某门课程中的信息,以(学号,课程)为主关键字的话,考察成绩、教室、教师、上课时间等都没有问题,考察教材时,因为教材应该仅依赖课程,考察学生信息(姓名、性别、专业),因为学生信息只依赖学生。这里存在违反第二范式的隐患。

上述表大致为
serialNo|姓名|专业|上课时间|上课地点|任课教授|资料|成绩
:———|:—:|:—:|:—:|:—:|:—:|:—:|:—:
120022001|王丫蛋|声乐|周三|12教102|Professor Steven|人教版|90
120022201|李铁锤|机械|周四|11教412|Professor Johnson|人教版|75
360022201|李铁锤|机械|周五|12教308|Professor Hassan|人教版|75
首先,调整部分依赖的字段会很麻烦:因考研大纲修改,开课改用外研社教材。需修改大量记录,李铁锤改名李婉如,修改大量记录,即数据冗余

其次,学校新设电子竞技课程,指定了教材,尚未有学生选课,数据是写不进去的,即插入异常

然后,哪天这门课程被教育部指定有悖社会主义核心价值体系,学校偷偷删除了所有选课记录,此时导致表中的学生信息大量遗失,即删除异常
因此应有课程-教材关系表 学号-学生信息关系表

第三范式

符合第二范式的关系模式(具备必要的关系表)中,不应出现依赖于非主属性的属性

例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在的员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。即消除了传递依赖

BCNF

根据候选键关系进一步消除传递依赖(没看懂)

第四范式

满足BCNF,属性不应含有多值,如联系方式相关字段的设计