114

我有兴趣了解您在非关系“nosql”数据库中使用的设计策略——即不使用传统关系设计或 SQL(例如 Hypertable、CouchDB、 SimpleDB、Google App Engine 数据存储、Voldemort、Cassandra、SQL 数据服务等)。它们通常也被称为“键/值存储”,并且在基础上它们就像巨大的分布式持久哈希表。

具体来说,我想了解这些新数据库在概念数据设计方面的差异。什么更容易,什么更难,什么不能做?

  • 您是否提出了在非关系世界中效果更好的替代设计?

  • 你有没有碰到任何看似不可能的事情?

  • 您是否使用任何设计模式弥合了差距,例如从一种模式转换到另一种模式?

  • 您现在是否甚至完全使用显式数据模型(例如在 UML 中),或者您是否完全放弃了它们以支持半结构化/面向文档的数据块?

  • 您是否错过了 RDBMS 提供的任何主要额外服务,例如关系完整性、任意复杂的事务支持、触发器等?

我来自 SQL 关系数据库背景,所以规范化在我的血液中。也就是说,我获得了非关系数据库在简单性和可扩展性方面的优势,而且我的直觉告诉我,设计能力必须有更丰富的重叠。你做了什么?

仅供参考,这里有关于类似主题的 StackOverflow 讨论:

4

5 回答 5

79

我才刚刚开始使用非关系数据库,而且我仍在努力思考它并找出最好的模型是什么。我只能代表 CouchDB。

不过,我有一些初步结论:

您是否提出了在非关系世界中效果更好的替代设计?

设计重点转移:文档模型(对应于数据库表)的设计变得几乎无关紧要,而一切都取决于设计视图(对应于查询)。

文档数据库交换了复杂性:SQL 具有不灵活的数据和灵活的查询,文档数据库则相反。

CouchDB 模型是“JSON 文档”(基本上是嵌套的哈希表)的集合。每个文档都有一个唯一的 ID,并且可以通过 ID 轻松检索。对于任何其他查询,您编写“视图”,它们被命名为 map/reduce 函数集。视图将结果集作为键/值对列表返回。

诀窍是您不会像查询 SQL 数据库那样查询数据库:运行视图函数的结果存储在索引中,并且只能查询索引。(如“获取所有内容”、“获取密钥”或“获取密钥范围”。)

SQL 世界中最接近的类比是,如果您只能使用存储过程查询数据库 - 您想要支持的每个查询都必须预先定义。

文件的设计非常灵活。我发现只有两个约束:

  • 将相关数据一起保存在同一个文档中,因为没有任何内容对应于连接。
  • 不要使文档太大以至于更新太频繁(例如将当年的所有公司销售额放在同一个文档中),因为每个文档更新都会触发重新索引。

但一切都取决于设计视图。

我发现使用 CouchDB 比任何 SQL 数据库更好的工作数量级的替代设计是在系统级别而不是存储级别。如果你有一些数据并且想要将它们提供给一个网页,那么整个系统的复杂度至少会降低 50%:

  • 没有设计数据库表(小问题)
  • 没有 ODBC/JDBC 中间层,所有查询和事务都通过 http (中等问题)
  • 来自 JSON 的简单 DB 到对象映射,与 SQL 中的映射相比,这几乎是微不足道的(重要!)
  • 您可以跳过整个应用程序服务器,因为您可以将文档设计为使用 AJAX 直接由浏览器检索,并在它们显示为 HTML 之前添加一点 JavaScript 修饰。(巨大的!!)

对于普通的 web 应用程序,基于文档/JSON 的数据库是一个巨大的胜利,而不太灵活的查询和一些额外的数据验证代码的缺点似乎是一个很小的代价。

你有没有碰到任何看似不可能的事情?

还没有。Map/reduce 作为一种查询数据库的方法是陌生的,并且比编写 SQL 需要更多的思考。原语数量相当少,因此获得所需的结果主要是如何指定键的创造性问题。

查询不能同时查看两个或多个文档是有限制的——没有连接或其他类型的多文档关系,但到目前为止没有什么是不可克服的。

作为一个示例限制,计数和总和很容易,但不能通过 CouchDB 视图/查询计算平均值。修复:分别返回 sum 和 count 并在客户端计算平均值。

您是否使用任何设计模式弥合了差距,例如从一种模式转换到另一种模式?

我不确定这是否可行。它更像是一种完全的重新设计,例如将功能风格的程序转换为面向对象的风格。一般来说,文档类型比 SQL 表少得多,每个文档中的数据多。

一种思考方式是查看插入和常见查询的 SQL:例如,当客户下订单时会更新哪些表和列?哪些是月度销售报告?该信息可能应该放在同一个文档中。

即: 一份订单文档,包含客户 ID 和产品 ID,并根据需要复制字段以简化查询。文档中的任何内容都可以轻松查询,任何需要在 Order 和 Customer 之间进行交叉引用的内容都必须由客户完成。因此,如果您想要一份按地区划分的销售报告,您可能应该在订单中输入地区代码。

你现在甚至做显式数据模型(例如在 UML 中)吗?

抱歉,在文档数据库之前也从未做过太多 UML :)

但是您需要某种模型来说明哪些字段属于哪些文档以及它们包含哪些类型的值。供您以后参考,并确保每个使用数据库的人都知道约定。例如,如果您在文本字段中存储日期不会再出现错误,并且任何人都可以添加或删除他们喜欢的任何字段,因此您需要验证代码和约定来弥补不足。特别是如果您使用外部资源。

您是否错过了 RDBMS 提供的任何主要的额外服务?

没有。但我的背景是 Web 应用程序开发人员,我们只在必须的范围内处理数据库 :)

我曾经工作的一家公司制造了一个产品(一个 web 应用程序),该产品旨在跨多个供应商的 SQL 数据库运行,并且“额外服务”因数据库而异,以至于必须为每个数据库单独实现。因此,将功能移出 RDBMS 对我们来说工作量更少。这甚至扩展到全文搜索。

因此,无论我放弃什么,都是我一开始从未真正拥有过的东西。显然,您的体验可能会有所不同。


一个警告:我现在正在做的是一个用于财务数据、股票报价等的网络应用程序。这非常适合文档数据库,从我的角度来看,我可以轻松获得数据库的所有好处(持久性和查询)。

但是这些数据彼此相当独立,没有复杂的关系查询。按股票代码获取最新报价,按股票代码和日期范围获取报价,获取公司元信息,这几乎就是全部。我看到的另一个例子是博客应用程序,博客也没有大量复杂的数据库模式。

我想说的是,我所知道的所有文档数据库的成功应用首先是与没有太多相互关系的数据:文档(如在谷歌搜索中)、博客文章、新闻文章、财务数据.

我希望有些数据集映射到 SQL 比映射到文档模型更好,所以我想 SQL 会继续存在。

但是对于我们这些只想要一种简单的方法来存储和检索数据的人——我怀疑我们当中有很多人——文档数据库(如在 CouchDB 中)是天赐之物。

于 2010-05-13T07:59:44.070 回答
55

我认为您必须考虑到非关系型 DBMS 在数据模型方面存在很大差异,因此概念数据设计也会有很大差异。在NOSQL Google 组的非关系数据库中的线程数据设计中,不同的范式分类如下:

  1. 类 Bigtable 系统(HBase、Hypertable 等)
  2. 键值存储(东京、伏地魔等)
  3. 文档数据库(CouchDB、MongoDB 等)
  4. 图数据库(AllegroGraph、Neo4j、Sesame 等)

我主要关注图形数据库,而使用这种范式的数据设计的优雅让我感到厌倦了RDBMS的缺点。我在这个wiki 页面上放了一些使用图形数据库进行数据设计的示例,并且还有一个如何对基本IMDB电影/演员/角色数据进行建模的示例。

Marko Rodriguez的演示幻灯片 (slideshare) Graph Databases and the Future of Large-Scale Knowledge Management也很好地介绍了使用图形数据库进行数据设计。

从graphdb的角度回答具体问题:

替代设计:在许多不同类型的实体之间添加关系,无需担心或需要预先定义哪些实体可以连接。

缩小差距:我倾向于根据域本身对每种情况进行不同的处理,因为我不想要“面向表格的图形”等。但是,这里有一些关于从 RDBMS 到 graphdb 的自动翻译的信息。

显式数据模型:我一直都在做这些(白板风格),然后也使用数据库中的模型。

来自 RDBMS 世界的小姐:创建报告的简单方法。更新:也许从图形数据库创建报告并不,请参阅为 Neo4J 示例数据库创建报告

于 2009-07-28T08:57:49.517 回答
11

我在脑海中用 CouchDB 回答这个问题,但我认为大多数其他数据库也是如此。我们考虑过使用 CouchDB,但最终决定不使用它,因为事先不知道我们的数据访问,而且可伸缩性不是问题。

更难:

  • 在概念层面上重新思考,所以它“更难”,因为它只是不同。由于您必须提前了解您的数据访问模式,因此无法应用自动翻译。您至少需要添加访问模式。
  • 一致性不由数据库处理,但必须在应用程序中处理。更少的保证意味着以更复杂的应用程序为代价更容易迁移、故障转移和更好的可扩展性。应用程序必须处理冲突和不一致。
  • 跨文档(或键/值)的链接也必须在应用程序级别处理。
  • SQL 类型的数据库具有更成熟的 IDE。你会得到很多支持库(尽管这些库的分层使事情比 SQL 所需的复杂得多)。

更轻松:

  • 如果您了解数据访问模式,则速度会更快。
  • 迁移/故障转移对数据库来说更容易,因为作为应用程序程序员没有向您做出任何承诺。虽然你得到了最终的一致性。大概。最后。一段时间。
  • 一个键/值比表中的一行更容易理解。所有(树)关系都已经存在,并且可以识别完整的对象。

建模应该大致相同,但您必须小心放在一个文档中的内容:UML 也可用于 OO 建模和 DB 建模,它们已经是两种不同的野兽。

我希望看到一个与 C#/Silverlight 完美集成的良好开放 OO 数据库。只是让选择变得更加困难。:)

于 2009-07-27T19:05:09.473 回答
1

对于任何大小的数据集,平面文件长期以来一直被认为是晦涩难懂且不切实际的。但是,具有更多内存的更快的计算机可以将文件加载到内存中并对其进行实时排序,至少对于相当小的 n 和本地单用户应用程序来说是这样。

例如,您通常可以在不到半秒的时间内读取包含 10,000 条记录的文件并按字段对其进行排序,这是可接受的响应时间。

当然,使用数据库而不是平面文件是有原因的——关系操作、数据完整性、多用户能力、远程访问、更大容量、标准化等,但是计算机速度和内存容量的提高使得内存操作成为可能在某些情况下更实用的数据。

于 2009-07-27T19:11:08.167 回答
1

我在现实生活中看到的关系数据库往往根本没有很好地规范化,这与您的说法相反。当被问及时,设计师告诉我这主要是因为性能。RDBM 不擅长连接,因此从规范化的角度来看,表往往过于宽泛。面向对象的数据库在这方面往往要好得多。

RDBM 存在问题的另一点是处理历史/时间相关键。

于 2010-08-24T19:01:16.433 回答