0

我们将在一个场景中使用 EAV 模式,其中我们将拥有具有非常不同属性的各种不同实体。

“基本” EAV 模式由 3 个表组成。由于不同的属性将具有不同的数据类型(日期、长整数、布尔值......),我目前正在考虑如何解决这个问题。

第一种方法是将所有内容存储为字符串。这需要“解析”,如果这是一个双精度、布尔值或任何东西,则不会直接显示像“1”这样的数字。属性值表看起来像

id|attribute_id|entity_id|value
1  2            3         17.0
2  4            2         Foobar

第二种方法是将不同的类型分成不同的列,使值列可以为空,例如:

id|attribute_id|entity_id|value_string|value_long|value_float|value_date
1  2            3         NULL         NULL       17.0        NULL
2  4            2         Foobar       NULL       NULL        NULL

然而,这会产生很多 NULL 值,这基本上就是为什么决定导致 EAV 模式的原因(减少未使用列中的 NULL 值)

因此,这导致了第三种可能的解决方案,即创建类型化的属性表:

attribute_values_string
id|attribute_id|entity_id|value
2  4            2         Foobar

attribute_values_float
id|attribute_id|entity_id|value
1  2            3         17.0

但是,这会使查询更加复杂,因为必须始终n检查表是否存在attribute_value. attribute_ids如果所有人都使用自己的auto_increment,那么像这样使用它也会导致不同的值类型相等。因此,将一个值转换为另一种类型可能有些棘手,因为它id无法维护。当然,这可以通过添加另一个attribute_values服务于 auto_increment 值并且可能包含一些类型信息和/或元数据的非类型表来避免。(因为我们需要使用版本控制/修订我们不能使用自动生成的属性值_ids,因为两个修订版仍然需要共享相同的 id)

所以,第一个决定是布局。有人有使用 EAV经验吗?每次尝试的瓶颈是什么?

4

3 回答 3

1

使用 NULL 方法。其他查询通常需要更多资源。

SQL Server 2008 提供了一些可以提供帮助的稀疏列。

此外,我可以看到您错过了实体实体的 Instance_Id 列具有属性,然后该实体有很多实例。您需要将其与 GUID 链接

于 2013-06-01T08:15:30.803 回答
1

Fwiw,我对你的第一个模式和你的第二个模式的变体有很好的经验。(类型列、单个值列和适当表达式的部分索引,即转换数据。使用 MySQL 最接近的是您的第二个模式:您关心的每种类型的列。)

如果您计划在第二个模式上添加索引,请不要忘记区分 value_string(对于您希望索引的短字符串,例如枚举等)和 value_text(对于不应被索引的长文本)。

不过,从长远来看,我实际上建议第一个选项,并带有通常的警告和注意事项:EAV 表唯一合理的长期用例是如果结构未定义并且存储在其中的实际数据是装饰性的东西。这里的操作词是未定义的和装饰性的。任何时候您真正想要或需要查询 EAV 表中的一条数据时,您都应该问自己应该如何修改架构以适应新列。不这样做会导致查询缓慢。

于 2013-06-01T09:23:31.170 回答
0

我理解您关于尝试减少 Null 值的观点,但是我相信 The 5 Normal forms总能解决这个问题。如果您的客户需要实时或按需添加属性,那么我同意 EAV 模型。

在我看到的许多其他问题中:

  1. 属性名称难以控制,难以统一;
  2. 难以强制执行数据类型完整性和引用完整性;
  3. 旋转和/或自连接值以形成单行是困难的(而且速度很慢);
  4. 很难强制某些属性;

我一直在使用 Magento,它需要大量缓存和辅助表才能“正常”工作,当然,保持其运行的服务器必须是强大的服务器。也许您的应用程序要小得多。

不管怎样,这只是我的意见,你,狗鼻子,也可以检查一下这个其他观点并做出自己的结论

于 2013-04-23T08:49:46.880 回答