面向列的NoSQL与面向文档的NoSQL有何不同?


89

我已经读过的NoSQL数据库的三种类型是键值,面向列和面向文档。

键值很简单-一个具有简单值的键。

我见过将面向文档的数据库描述为键-值,但该值可以是结构,例如JSON对象。每个“文档”可以具有全部,部分或相同的键。

面向列似乎很像面向文档,因为您没有指定结构。

那么,这两者之间有什么区别,为什么您要使用一个而不是另一个呢?

我专门研究了MongoDB和Cassandra。我基本上需要一个可以更改但不影响其他值的动态结构。同时,我需要能够搜索/过滤特定键并运行报告。有了CAP,AP对我来说是最重要的。只要不存在数据冲突或丢失,就可以“最终”跨节点同步数据。每个用户将获得他们自己的“表”。

Answers:


41

在Cassandra中,每一行(用键寻址)都包含一个或多个“列”。列本身就是键值对。列名不需要预定义,即结构不是固定的。行中的列根据其键(名称)以排序的顺序存储。

在某些情况下,一行中的列可能非常多(例如,用作启用特定种类查询的索引)。Cassandra可以有效地处理如此大的结构,并且您可以检索特定范围的列。

还有一个称为超级列的结构(不是很常用),其中一列包含嵌套的(子)列。

您可以将整体结构视为嵌套的哈希表/字典,具有2或3个级别的键。

普通列族:

row
    col  col  col ...
    val  val  val ...

超级列族:

row
      supercol                      supercol                     ...
          (sub)col  (sub)col  ...       (sub)col  (sub)col  ...
           val       val      ...        val       val      ...

还有更高层次的结构-列族和键空间-可用于将数据划分或组合在一起。

另请参阅此问题:Cassandra:什么是子列

或来自http://wiki.apache.org/cassandra/ArticlesAndPresentations的数据建模链接

回复:与面向文档的数据库进行比较-后者通常插入整个文档(通常为JSON),而在Cassandra中,您可以处理单个列或超列,并分别进行更新,即它们以不同的粒度级别工作。每列都有自己单独的时间戳记/版本(用于协调分布式集群中的更新)。

Cassandra列的值仅为字节,但可以键入为ASCII,UTF8文本,数字,日期等。

当然,您可以通过插入包含JSON的列来将Cassandra用作原始文档存储-但是您不会获得真正的面向文档的存储的所有功能。


5
列族就像一张桌子。行就像表格行。列有点像数据库列,但它们可以动态定义,因此在某些情况下,您的表可能非常稀疏,或者每一行中可能填充不同的列。
DNA

1
它取决于数据库。在MongoDB(面向文档)中,您还可以更新每个键。
David Raab

1
如果是这样,那么MongoDB如何定义一个面向文档的数据库,而Cassandra是面向列的。它们有何不同?
路加福音

3
@Luke面向列的看上去很像无模式的RDBMS,但是除了其松散的结构外,主要区别在于它不是关系型的。
user327961 2011年

1
@ user327961但是MongoDB也像无模式的RDBMS一样,它也不是关系型的。
huggie 2014年

54

主要区别在于文档存储区(例如MongoDB和CouchDB)允许任意复杂的文档,即子文档内的子文档,带有文档的列表等,而列存储区(例如Cassandra和HBase)仅允许使用固定格式,例如严格的一级或两级字典。


在这种情况下,mongo(document)可以做cassendra(Column)可以做的事情。那么为什么需要Column?
sanjay patel

1
这是不同功能之间的折衷,采用面向列的设计,存储引擎可以比面向文档的存储引擎更高效。如果MongoDB变得更大,则必须重写磁盘上的整个文档,但Cassandra不必重写(这是一种简化,当然,有很多细节)。这使得Cassandra的编写速度更快。
Theo

29

在“插入”中,要使用rdbms单词,基于文档的格式更加一致和直接。请注意,使用cassandra可以使您与仲裁概念保持一致,但这并不适用于所有基于列的系统,并且会降低可用性。在一次写入/经常读取的繁重系统上,请使用MongoDB。如果您始终打算阅读对象的整个结构,也请考虑一下。基于文档的系统旨在在您获取整个文档时将其返回,并且在返回整个行的某些部分方面并不是很强大。

像Cassandra这样的基于列的系统在“更新”中比基于文档的系统要好得多。您可以更改列的值,甚至无需读取包含它的行。实际上并不需要在同一服务器上完成写操作,多服务器的多个文件中可能包含一行。在庞大的快速发展的数据系统上,请选择Cassandra。如果您计划每个键包含非常大的数据块,并且不需要在每次查询时都加载所有数据,也请考虑一下。在“选择”中,Cassandra允许您仅加载所需的列。

还应考虑到Mongo DB是用C ++编写的,并且是第二个主要版本,而Cassandra需要在JVM上运行,并且它的第一个主要版本仅在昨天才发布(但是0.X版本已在大公司)。

另一方面,Cassandra的设计部分基于Amazon Dynamo,并且其核心是作为高可用性解决方案而构建的,但这与基于列的格式没有任何关系。MongoDB也可以扩展,但不如Cassandra优雅。


1
用C ++和Java编写的软件有什么问题?
Nayuki

@Nayuki现在,我知道在某些竞争激烈的工作负载中,Java的内存管理模型的惰性垃圾回收理论上将比C ++的“手动”管理模型更好,但是通常来说,通过编写等效的书来超越Java通常并不困难至少在禁用Exceptions和RTTI的前提下使用C ++编写程序。而且,如果您充分利用了无栈协程和可恢复功能,那么我个人还没有看到Java胜过我的C ++。
patrickjp93

0

我要说的主要区别在于,每种数据库类型在物理上存储数据的方式。
对于列类型,数据按列存储,这可以对特定列进行有效的聚合操作/查询。
对于文档类型,整个文档在逻辑上存储在一个位置,并且通常作为一个整体进行检索(“列” /“字段”上不可能进行有效的聚合)。

令人困惑的一点是,宽列“行”可以轻松地表示为文档,但是,如上所述,它们以不同的方式存储和针对不同的目的进行了优化。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.