非关系数据库设计

Posted

技术标签:

【中文标题】非关系数据库设计【英文标题】:Non-Relational Database Design [closed] 【发布时间】:2010-11-14 11:09:14 【问题描述】:

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

具体来说,我想了解概念数据设计与这些新数据库的区别。什么容易,什么难,什么不能做?

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

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

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

您现在是否甚至在做显式数据模型(例如在 UML 中),还是完全放弃了它们,转而支持半结构化/面向文档的数据 blob?

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

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

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

the next generation of databases changing schemas to work with Google App Engine choosing a document-oriented database

【问题讨论】:

键/值数据库旧事物。 对于任何超级感兴趣的人,NoSQL 谷歌小组正在进行一个长篇讨论,这里:groups.google.com/group/nosql-discussion/browse_thread/thread/… 仅供参考,我已经写了一篇关于这个主题的长篇报告,在这里:google.com/url?sa=D&q=http://ianvarley.com/UT/MR/… 感谢大家的帮助! 【参考方案1】:

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

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

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

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

文档数据库有点交换复杂性: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 对我们来说工作量更少。这甚至扩展到全文搜索。

所以无论我放弃什么,我一开始都没有真正拥有过。显然,您的体验可能会有所不同。


需要注意的是:我现在正在开发一个用于财务数据、股票报价等的网络应用程序。这与文档数据库非常匹配,从我的角度来看,我获得了数据库的所有好处(持久性和查询)而没有任何麻烦。

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

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

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

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

【讨论】:

非常有用。尤其是“SQL 有不灵活的数据和灵活的查询,文档 DB 则相反”以及没有连接。 +1,这非常有见地。 确实如此,如果可能的话,我会多次投票。 这在 2014 年仍然非常有用,如果您可以添加自 2010 年以来学到的知识或链接到您在其他地方可能拥有的信息,那就太好了。【参考方案2】:

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

    类 Bigtable 系统(HBase、 Hypertable 等) 键值存储(东京、伏地魔、 等) 文档数据库(CouchDB、 MongoDB 等) 图形数据库(AllegroGraph, Neo4j、芝麻等)

我主要喜欢graph databases,正是使用这种范式的优雅数据设计让我感到厌倦了RDBMS 的缺点。我在wiki page 上放了一些使用图形数据库进行数据设计的示例,还有一个example of how to model 基本的IMDB 电影/演员/角色数据。

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

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

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

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

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

RDBMS 世界的小姐:创建报告的简单方法。更新:也许从图形数据库创建报告并不难,请参阅Creating a Report for a Neo4J Sample Database。

【讨论】:

【参考方案3】:

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

更难:

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

更简单:

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

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

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

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

【参考方案5】:

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

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

【讨论】:

Stephan - 你说得对,现实世界的系统通常缺乏标准化部门。但是说RDBMses“不擅长加入”是不准确的;大多数商业产品(如 Oracle、MS SQL Server 等)都具有极其先进的查询优化器,并且可以执行各种不同的物理连接算法,比在应用程序代码中执行相同的操作要快得多。 (据我了解,mysql 是一个例外)。根据我的经验,过早的非规范化与其他过早的优化一样,通常是开发人员不佳的标志。 继续这个想法:糟糕的连接是糟糕的索引和统计数据的结果。如果优化器没有可使用的东西,或者它所拥有的信息已经过时,它将做出糟糕的选择。许多人将此误认为是“加入不佳”。现代 RDBM 系统具有自我调整功能,这掩盖了在设置索引和统计信息时使用大脑的需要。此外,人们混淆了逻辑模式(第五范式)和物理模式(经常非规范化为第三范式)。仅仅因为您看到的数据库“宽”并不意味着它在逻辑上设计不佳。

以上是关于非关系数据库设计的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL01_数据库的概述关系型和非关系型数据库区别设计规则

如何在非关系数据模型上构建关系 Java 对象模型?

非关系型数据库——HBase扩展

关系型数据库与非关系型数据库的区别

非关系型数据库实训-大数据平台及应用

非关系型数据库实训-大数据平台及应用