我是最近才开始接触文档型数据库,以前只玩儿过关系型数据库 Mysql
在mysql 里面,创建多对多关系,比如学生和课程的关系,是这样创建的:
1.学生表
2.课程表
3.学生对应课程中间表
但是最近看mongodb,发现文章里面大多数都是这样讲的:先将学生放在一个集合中, 再把每个人报名课程的情况放到另外的一个集合当中, 最后在学生集合中引用那个报名情况集合当中的ObjectId
最后就变成了这样:
1.学生表
2.每个学生的报名情况表
Why?
我知道文档型数据库的实现与关系型数据库的实现不一样,但是这样放不会有很多冗余数据吗?为什么不像关系型数据库那样,采用一个中间表放 学生ID
以及对应的 课程ID
。只是为了编程的时候,方便查询操作?
这是一个取舍的问题。
在做一个项目的时候你为什么选择文档数据库而不是关系数据库?文档数据库并不是完美的,比如冗余。但是它也能提供很多关系数据库提供不了的东西,比如水平扩展,高性能。同样关系数据库也不是完美的,提供事务支持的同时就舍弃了分布式的可能性(CAP理论)。接触得越多,你会发现很多这样的特性,有些无论关系非关系数据库都支持,有些就只能在一边支持(或者说一边支持得更好)。所以什么对你是最重要的?在你选择了最重要的特性时,就可能需要在一定程度上放弃其他特性。
拿你的例子来说,
JOIN
在关系数据库中是再平常不过的事情,但是你可能没有完全了解它对性能的损伤有多大。特别是到了分布式环境下,这意味着每个结点要与其他所有结点通讯才能确定最终的结果集。虽然理论上可以做到,但是对性能的影响可以说让非关系数据库的性能优势直接大打折扣(比如如果你的集群中有100个结点时,每条需要JOIN
的数据所在的服务器都要与其他99台通讯才能确定结果)。因为大部分人选择非关系数据库是希望得到水平扩展和高性能的,如果这些对你更重要,那舍弃JOIN
当然就是必然的选择了。那么如果不要JOIN
,就必须要有冗余,所以最终的问题变成,水平扩展和高性能,以及数据冗余,到底哪个对你来说更重要?如果我能容忍数据冗余,会带来什么问题?可以想象一下,冗余了课程信息,那么在报名过程中,有多大的可能性对课程本身做修改?常识来讲可能性是很小的。所以这里的冗余除了浪费空间外,还有很小的可能性在课程修改时造成需要大量更新,以及更新过程中的数据不一致情况。浪费空间会是个问题吗?你可能听说过这样的说法:存储空间是服务器中最廉价的部分。这点不多做解释了,基本上不会太在乎空间。
大量更新和数据不一致会是个问题吗?会,但是它有多大可能性发生?那么拿很小可能性发生的一个问题,交换大部分时间内性能大幅度提高,是不是更划算?
实际应用当中,根据实际情况的来评估哪个更划算,很大部分时候你会发现,其实冗余理论上有问题,但实际中根本没影响,或者可以通过一些手段让这些问题不能造成影响。那么就可以既享受性能优势,又不影响系统逻辑,这就是最好的情况。
还有一小部分时候你会发现,冗余确实会造成严重的问题,那这就是选择范式模型的时候了。如果应用严重依赖范式,那就应该选择在这个系统中选择关系数据库。