【问题标题】:Dynamic Database/Key - Value/Entity - Key Value Dillemma动态数据库/键 - 值/实体 - 键值困境
【发布时间】:2012-01-26 10:22:07
【问题描述】:

我从事关系数据库编程多年,但现在遇到了一个不寻常且棘手的问题:

我正在构建一个应用程序,该应用程序需要具有非常快速且易于定义的实体(由用户)。然后可以创建、更新、删除这些实体的实例等。

我能想到两种选择。

选项 1 - 动态创建的表

第一个选项是编写一个引擎来动态生成表,并将数据插入到这些表中。但是,这会变得非常棘手,因为每个查询也需要是动态的,或者至少是动态创建的存储过程等。

选项 2 - 实体 - 键 - 值模式

这是我能想到的唯一现实的选择,我有 5 个表结构:

实体类型

EntityTypeID int

EntityTypeName nvarchar(50)

实体

EntityID 整数

EntityTypeID int

字段类型

FieldTypeID 整数

字段类型名称 nvarchar(50)

SQLtype int

字段值

EntityID 整数

FIeldID 整数

值 nvarchar(MAX)

字段

FieldID 整数

字段名 nvarchar(50)

FieldTypeID 整数

“FieldValues”表的工作方式有点像数据仓库事实表,我的所有插入/更新都将通过填充“键/值”表值参数并将其传递给 SPROC 来工作(以避免多次插入/更新)。

所有的表都会被大量索引,我最终会做很多自连接来获取数据。

我已经阅读了很多关于键/值数据库有多糟糕的信息,但对于这个问题,它似乎仍然是最好的。

现在我的问题!

  • 除了这两个选项之外,任何人都可以提出其他方法或模式吗?
  • 对于中等规模的数据集(最大 100 万行),选项 2 是否可行?
  • 我可以使用选项 2 的进一步优化吗?

非常感谢任何方向和建议!

【问题讨论】:

  • 玩了一会之后,我让 Mongo 与 Mongo/C# library 一起运行。对于这个特定示例,noRM 库的类型有点太强了,因为我将使用诸如 db.getCollection("Contacts") 之类的命令。感谢 pablochan 为我指明了正确的方向,并期待使用 noSQL 进行新的冒险!

标签: sql database non-relational-database object-relational-model


【解决方案1】:

我个人只会使用“noSQL”(键/值)数据库,例如MongoDB

但如果您需要使用关系数据库选项 2 是要走的路。这种模型的一个很好的例子是Alfresco Data Dictionary(Alfresco 是一个企业内容管理系统)。它的设计与您描述的相似,尽管它们有多个字段值列(对于数据库中可用的每种简单类型)。如果您向其中添加一个好的缓存系统(例如Ehcache),它应该可以正常工作。

【讨论】:

  • 感谢 cmets。没听说过noSQL 数据库,简单看了一下MonogDB 看起来很有趣。我将浏览本教程,看看我是否看到了前进的方向。你知道它是否可以很好地扩展,并且适用于多用户 Web 应用程序吗?我正在使用带有 C# 的 ASP.NET MVC3。
  • 不幸的是,我没有使用 MongoDB 的“真实生活”体验,所以我无法真正告诉你。问题之一是写操作阻塞了整个数据库(mongodb.org/display/DOCS/How+does+concurrency+work),至少在这一点上,所以你一定要仔细阅读它。不过还有其他 noSQL 数据库,因此您也可以查看它们。
【解决方案2】:

正如其他人建议的 NoSQL,我要说的是,在我看来,无模式数据库确实最适合没有模式的用例。

从描述和您想出的架构看来,您的情况实际上并不是“无架构”,而是“用户定义的架构”。

事实上,您提出的架构看起来非常类似于关系数据库的内部元架构。 (您是在关系数据库之上构建一个关系数据库,以我的经验,这不是一个好主意,因为这个“元数据库”对于任何基本操作来说至少会有两倍的开销和复杂性 - 表将变得非常大,扩展性不好,数据会很难查询更新,问题很难调试等等。)

对于这样的用例,您可能需要 DDL:数据定义语言。

您没有说您使用的是哪个 SQL 数据库,但大多数 SQL 数据库(例如 MySQL、PostgreSQL 和 MS-SQL)都支持 SQL 语法的某些 DDL 扩展方言,这让您可以操作实际的架构。

过去,我已经成功地为像您这样的用例做到了这一点。它适用于架构很少更改并且每个用户的数据量相对较低的情况。 (对于大量或频繁的模式更新,您可能需要无模式或其他类型的 NoSQL 数据库。)

您可能需要一些表来存储不适合 SQL 架构的其他字段信息 - 您可能还想在此处复制一些架构信息,因为从实际架构中读取可能很困难或效率低下。

确保对您的字段信息表和架构进行原子更新可能需要事务,您的数据库引擎可能不支持该事务 - PostgreSQL 至少支持事务架构更新。

当涉及到安全性时,您必须保持警惕 - 您不想让用户自己创建、存储或删除他们不应该做的事情。

如果它适合您的用例,请考虑使用单独的表和单独的数据库,也可以使用 DDL 按需创建和销毁。如果每个客户都拥有不能、不应该或不需要跨客户查询的数据集合的所有权,这可能适用。 (可以说,这些很少见 - 通常,您至少需要跨客户的分析或其他东西,但在某些情况下,每个客户都“拥有”一个独立的托管 wiki、商店或某种形式的 CMS/DMS。)

(我在您的评论中看到您已经决定使用 NoSQL,因此为了完整起见,仅在此处发布此选项。)

【讨论】:

  • 这个答案是正确的。这个问题是 10 年前提出的,我们绕了一圈。我们在 MongoDb 上构建了解决方案,但大约 3 年后,我们迁移到 Postgres,完全按照你说的做 - 让关系数据库完成其工作并动态修改模式。我们最终构建了一个声明式架构工具,它将采用架构定义并自动迁移数据库。
【解决方案3】:

听起来这可能是寻找问题的解决方案。您的域是否有可能被重构?如果没有 - 还有希望。

  • 选项 2 的可扩展性很大程度上取决于自定义对象的宽度。可以动态创建多少个字段?当每个实体有 100 个字段时,100 万个实体可能会很麻烦...高效的索引可以使性能可以承受。

  • 对于另一种选择 - 您可以拥有一个包含几个字符串字段、几个双精度字段和几个整数字段的数据表。例如,带有String1, String2, String3, Int1, Int2, Int3 的表。第二个表具有定义用户对象并映射您的“CustomObjectName”=> String1 等的行。读取 INFORMATION_SCHEMA 和一些动态 sql 的存储过程将能够读取模式表并返回强类型记录集...

  • 另一个选项(对于 SQL Server 的最新版本)是存储一行,其中包含一个 id、一个类型名称和一个 XML 字段,该字段包含一个包含对象数据的 XML 文档。在 MS Sql Server 中,可以直接查询,甚至可以根据模式进行验证。

【讨论】:

    【解决方案4】:

    就我个人而言,我会花时间定义尽可能多的属性,而不是对所有内容都使用 EAV。你肯定知道一些属性。然后,您只需要 EAv 来处理真正特定于客户的事情。

    但如果一切都必须是 EAV,那么一个 nosql 数据库就是要走的路。或者,您可以对某些内容使用关系数据库,对其余内容使用 nosql 数据库。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-19
      • 2011-12-25
      • 2017-10-08
      • 1970-01-01
      • 2021-12-24
      • 1970-01-01
      • 2021-03-30
      • 2012-01-28
      相关资源
      最近更新 更多