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

Posted

技术标签:

【中文标题】面向列的 NoSQL 与面向文档的 NoSQL 有何不同?【英文标题】:How does column-oriented NoSQL differ from document-oriented? 【发布时间】:2011-11-25 18:32:49 【问题描述】:

我读过的三种 NoSQL 数据库是键值、面向列和面向文档。

键值对非常简单 - 一个具有普通值的键。

我见过将面向文档的数据库描述为键值对,但值可以是结构,例如 JSON 对象。每个“文档”可以具有所有、一些或没有与另一个相同的键。

面向列似乎与面向文档非常相似,因为您无需指定结构。

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

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

【问题讨论】:

【参考方案1】:

在 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: What is a subcolumn

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

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

Cassandra 列值只是字节,但可以输入为 ASCII、UTF8 文本、数字、日期等。

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

【讨论】:

列族就像一张表。一行就像一个表格行。列有点像数据库列,只是它们可以动态定义,因此在某些情况下,您可能拥有一个非常稀疏的表,或者您可能在每一行中填充了不同的列。 这取决于数据库。在 MongoDB(面向文档)中,您还可以更新每个键。 如果是这样,MongoDB 是如何定义面向文档的数据库而 Cassandra 是面向列的。它们有何不同? @Luke 面向列看起来很像一个无模式的 RDBMS,但除了结构松散之外,主要区别在于它不是关系型的。 @user327961 但是 MongoDB 也像一个无模式的 RDBMS,它也不是关系型的。【参考方案2】:

在“insert”中,使用rdbms的话,Document-based更加一致和直接。请注意,cassandra 可以让您实现与仲裁概念的一致性,但这并不适用于所有基于列的系统,并且会降低可用性。在一次写入/经常读取的繁重系统上,选择 MongoDB。如果您总是打算阅读对象的整个结构,也请考虑一下。基于文档的系统被设计为在获取时返回整个文档,并且在返回整行的部分方面不是很强大。

Cassandra 等基于列的系统在“更新”方面比基于文档的系统要好得多。您甚至可以在不读取包含它的行的情况下更改列的值。写入实际上不需要在同一台服务器上完成,一行可能包含在多个服务器的多个文件中。在庞大的快速发展的数据系统上,选择 Cassandra。如果您计划每个键有非常大的数据块,并且不需要在每个查询中加载所有数据,也可以考虑它。在“选择”中,Cassandra 让您只加载您需要的列。

另外考虑一下 Mongo DB 是用 C++ 编写的,并且是它的第二个主要版本,而 Cassandra 需要在 JVM 上运行,并且它的第一个主要版本是从昨天开始的候选版本(但 0.X 版本已经转向已经在大公司的生产中)。

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

【讨论】:

用 C++ 和 Java 编写的软件有什么问题? @Nayuki 现在,我知道 Java 内存管理模型的惰性垃圾收集在理论上会胜过 C++ 的“手动”管理模型,但一般来说,这通常不会很难通过用 C++ 编写等效程序来超越 Java,至少只要您禁用 Exceptions 和 RTTI。如果你充分利用了无堆栈协程和可恢复函数,那么我个人还没有看到 Java 击败我的 C++。【参考方案3】:

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

【讨论】:

在这种情况下,mongo(document) 可以做 cassendra(Column) 可以做的事情。那么为什么需要列呢? 这是不同功能之间的权衡,使用面向列的设计,存储引擎可以比面向文档的存储引擎更有效。如果 MongoDB 变大,它必须在磁盘上重写整个文档,但 Cassandra 不必(这是一种简化,当然,这有很多细节)。这使得 Cassandra 的写作速度更快。 更正命名和理解:Cassandra 和 Hbase 是列“家庭”存储,而不是列“面向”存储(又名列存储)。 CF 按行存储数据(= 面向行的存储),CO 按列存储数据。参考:community.datastax.com/answers/6244/view.html【参考方案4】:

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

令人困惑的是,宽列“行”可以很容易地表示为一个文档,但是,如前所述,它们的存储方式不同,并且针对不同的目的进行了优化。

【讨论】:

以上是关于面向列的 NoSQL 与面向文档的 NoSQL 有何不同?的主要内容,如果未能解决你的问题,请参考以下文章

常用的NoSQL数据库类型简述

Redis技法篇 - 1. Redis的安装与配置

面向 Java 开发者的 NoSQL 选项

Nosql中MongoDB的介绍

砺锋资讯面向 Java 开发者的 NoSQL 选项

为啥说hbase是一个面向列的数据库