数据库设计:EAV选项?

3

这只是一个关于数据库概念的问题:以下是EAV模型的优缺点:

模型1:

TABLE: attribute_value
======================================
| id | fk_id | attribute | value     |
======================================
| 1  | 10    | FName     | John      |
| 2  | 10    | Lname     | Doe       |
| 3  | 55    | FName     | Bob       |
| 4  | 55    | Lname     | Smith     |
--------------------------------------

Model 2:

TABLE: attribute
==================
| id | attribute |
==================
| 1  | FName     |
| 2  | Lname     |
------------------

TABLE: value
=====================================
| id | attribute_id | fk_id | value |
=====================================
| 1  | 1            | 10    | John  |
| 2  | 2            | 10    | Doe   |
| 3  | 1            | 55    | Bob   |
| 4  | 2            | 55    | Smith |
-------------------------------------

我认为模型2的一个优点是属性不包含重复项。


2
缺点:EAV 非常难以优化。一段时间后,你会陷入无法编写快速工作的查询的困境中。 - zerkms
3个回答

5
尽管Model2的属性表看起来很简洁,但引入了元数据概念,带来了诸多好处。除了Value表行大小更小(性能提升)等优点外,我想重点介绍元数据概念。
即使是现有的Model2属性表本身也构成了所有有效属性的存储库(使用Model1需要运行某种聚合查询才能获得此类列表)。此外,现有的存储库足以引入外键约束,以帮助维护数据集的完整性(使用Model1需要对属性列中存储的值进行外部验证)。
通过添加一些简单的内容,属性表可以成为可用于各种目的的多功能存储库。例如,该表可以包括以下内容:
- 每个属性的显示友好名称等信息 - 一些指示字段类型(数字、字符串、日期等)的标志,以进行区分处理/处理 - 存储基础属性的特定Value表(Model仅显示一个表,但优化/扩展有时会提示拆分表) - 属性可能作为自己的列存储在“值”表中的事实(再次是一种优化形式,基本上同时获得EAV模型的模式灵活性和传统关系模型的性能,用于最常用和/或最常见于所有实体的属性) - 无需干扰主表即可重命名属性。仅在元数据级别进行更改。 - 各种应用程序相关的语义。例如,指示特定属性是否应作为基本搜索字段或高级搜索字段之一提供。
简而言之,属性表成为一个资源,允许应用程序真正以数据驱动(或更准确地说,以元数据驱动)。实际上,您可能还需要一个实体表,即收集有关各种实体类型的元数据的表:哪些是不同的实体类型,哪些属性适用于哪些实体类型等。
现在……请注意zerkms在问题本身下方的评论。尽管EAV模型具有许多优点,但也存在缺点和挑战,例如复杂的查询和性能问题。然而,这些问题不应该从根本上否定EAV:在许多用例中,EAV是更好的方法。假设选择EAV,则Model2甚至稍微复杂一些的东西肯定比Model1更好。

mjv - Model 2仍被认为是EAV吗? - StackOverflowNewbie
1
@StackOverflowNewbie - 是的,绝对是。使其成为EAV的关键概念是“主”表(模型中的“值”表)捆绑了所有3个元素:实体(fk_id),属性(attribute_id)和值。属性只是作为[数字] id而不是像model1的属性列中显示的一些文本存在,但这一事实肯定不会消除设计的EAV性质。 - mjv

1

从概念层面上看,这两个模型几乎是相同的。你只是用ID号码替换了字符串而已。仅此而已。

至于外键,如果你愿意,你可以在模型1中对"attribute"施加外键约束。

就利弊而言,这两种EAV的实现方式实际上没有任何区别。所有Bill Karwin的观点都适用于两者。


0

对于模型2,您可以在attribute_id上强制实施外键,并确保只有定义的属性可以进入表中。

同样对于模型2,您可以更快地查询具有特定属性ID的值,因为如果您创建一个外键(索引),查询将更快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接