数据库设计:EAV选项



这只是一个数据库概念问题:以下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     |
--------------------------------------
模型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的一个好处是attribute不包含重复项。

虽然如图所示是极简的,但Model2的属性表引入了元数据的概念,并从中获得了所有好处。Model2还有其他优点,例如性能增益与较小的行大小(Value表的行大小)相关,但是我想关注元数据概念。

甚至原样 Model2的属性表也构成了所有有效属性的存储库(对于model1,需要运行排序的聚合查询来获得这样的列表)。而且,按原样,存储库足以引入外键约束,以帮助维护数据集的完整性(对于模型1,需要对存储在属性列中的值进行外部形式的验证)。

通过一些简单的添加,属性表可以成为一个多功能存储库,可以用于各种目的。例如,表可能包含以下内容

  • 信息,例如每个属性的显示友好的名称
  • 一些指示字段类型的标志(数字、字符串、日期等),用于区分处理/处理
  • 存储底层属性的特定Value表(模型只显示一个表,但优化/扩展有时会提示拆分表)
  • 属性可以作为自己的列存储在"值"表中的事实(又是一种优化形式,本质上是两全美:EAV模型模式的灵活性,但对于所有实体最常用和/或最常见的属性,传统关系模型的性能。)
  • 能够在不干扰主表的情况下重命名属性。仅在元数据级别更改。
  • 各种面向应用的语义。例如,指示应该提供特定属性作为基本和高级搜索字段之一。
简而言之,属性表成为了一种资源,它允许应用程序成为真正的数据驱动(或者更准确地说,meta数据驱动)。事实上,你可能也喜欢一个实体表,即收集与各种实体类型有关的元数据的实体表:哪些是不同的实体类型,哪些属性允许用于哪个实体类型等。

现在…一定要注意问题下方来自zerkms的评论。尽管EAV模型有很多优点,但它也有一些缺点和挑战,比如查询的复杂性,以及性能问题。然而,这些问题不应该先验地取消EAV的资格:在许多用例中,EAV是一种更好的方法。
假设EAV是选择,那么Model2,甚至稍微复杂一点的东西肯定优于model1。

在概念层面上,这两个模型实际上是相同的。您只是将字符串替换为ID号。就是这样。

就外键而言,如果您愿意,可以在模型1中的"attribute"上施加外键约束。

就利弊而言,这两种EAV实现之间实际上没有区别。

对于模型2,您可以在attribute_id上强加一个Foreign-Key,并确保只有定义的属性可以进入表。

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

最新更新