2

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

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

我能想到的有两种选择。

选项 1 - 动态创建的表

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

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

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

实体类型

EntityTypeID 整数

实体类型名称 nvarchar(50)

实体

实体ID int

EntityTypeID 整数

字段类型

字段类型ID int

字段类型名称 nvarchar(50)

SQLtype int

字段值

实体ID int

字段 ID 整数

值 nvarchar(MAX)

字段

字段 ID 整数

字段名称 nvarchar(50)

字段类型ID int

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

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

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

现在我的问题!

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

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

4

4 回答 4

3

就我个人而言,我只会使用像MongoDB这样的“noSQL”(键/值)数据库。

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

于 2011-12-22T21:15:20.800 回答
1

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

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

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

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

于 2011-12-22T21:05:57.963 回答
1

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

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

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

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

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

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

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

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

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

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

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

于 2021-09-11T08:48:43.660 回答
0

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

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

于 2014-10-31T14:50:42.373 回答