EAV

Entity–attribute–value model (EAV) is a data model to encode, in a space-efficient manner, entities where the number of attributes (properties, parameters) that can be used to describe them is potentially vast, but the number that will actually apply to a given entity is relatively modest. Such entities correspond to the mathematical notion of a sparse matrix. EAV is also known as object–attribute–value model, vertical database model and open schema.

简单入门

英语原文

EVA 模型

解决的问题

EAV 方法适合符合该实体的参数数量远大于具体某一实体所包含的参数数量时的情况。

  • 问题

多种类的数据必须表现出来,其数量可能出现波动。与此同时,即使不稀疏的属性,然每类数据都非常少。这种情况下,传统的数据模型将使成百的表却只有几行数据。

  • EAV

为解决上述问题,可应用EAV(Entity,Attribute,Value)模型。 这种模式也有几个可选的称谓,包括“对象-属性-值(object—attribute-value)”模型和“开放架构(open schema)”几种可供选择的名称。 在EAV数据模型中,只有非空值才存储在数据库中,每个属性-值(或键-值)对描述一个给定实体的属性。 EAV表经常定性为“长瘦(long and skinny)”的,“长”是指描述实体的多个行,而“瘦”则指仅使用少量的列。

对象属性存储在一个有三列的表中:实体,属性和值(entity,attribute,value)。

实体(entity)表示所描述的数据项,例如一个产品或汽车。 属性(attribute)表示描述实体的数据,例如一个产品将有价格,重量和许多其他属性。 值(value)是属性的值,例如产品可能有一个9.99英镑的价格属性。 此外值可以基于数据类型进行分割,所以可将EAV表分为字符串、整数、日期和长文本(long text)表。 依据数据类型分割是为了支持索引,使得数据库执行可能的类型检查验证。

稀疏的属性

在数学和计算机科学中,如果一个对象仅包含大量潜在属性中的几个属性,称之为“稀疏矩阵”。

在讨论EAV模型时,采用“稀疏”来描述大多数无值的属性。

为说明这一点,来看看超市的收据,超市中有成千上万的库存产品,每日引入新的产品,其它则停止销售。 客户购买5个产品的收据只列出实际购买的详细项目,每行一种产品。该收据并没有列出客户可能购买的每一种产品,所以说客户的收据是稀疏的。

按照数据库的术语实体是销售发票,包含如交易ID、日期和时间、存放位置等信息,收据中的每一行对应销售表中的一行记录,存有一个属性及一个或多个值。 在这种情况下,属性之一是客户所购买的产品,值则为的数量、单价、折扣和总价。

上面的例子说明了属性的稀疏性(一个客户只选购一个可能的产品), 引入一个新的术语:行建模(row modelling)。 基于行模型的表,其描述实体的数据记录为多行,每组新的数据在数据库中存为额外的行而非额外的列。行模型是数据库设计时的标准数据建模技术,它仅适用于满足如下两个条件的情况:

  • 特定实体的数据是稀疏的。

  • 数据是易变的。

行建模是不适用于稀疏且数据非波动的情形,此时,应采用传统的列模型。

行模型示例

在这个例子中,有三个实体:产品,客户和发票。产品和客户是标准的关系表。

正如本文前面提到的,满足(上文所述的)两个条件时行模型需是一个不错的选择,即特定实体的数据稀疏,且很容易变化。

我们知道,新产品不断推出且被引入销售,而旧的产品撤回。同时,发票表中不能对每种产品以一列来描述,因为这是不切实际的。

该发票表包含有关销售活动的主要信息,客户、日期和时间、发票ID。每张发票,在表中记录为一行。每一行指定了(顾客)购买的产品、单价和数量。

EAV 与行模型比较

实体-属性-值的设计是行模型的泛化(或)推广。 这意味着整个数据库所有类型的数据存储在一张表中,其中一个行模型的表的数据时是均匀。 此外,这行模型表中值列的数据类型是预先确定的,而在一EAV表中,特定行其值的数据类型由对应的属性确定。

选择数据模型的最佳方法是很难的,但作为一个准则,如满足如下条件时请考虑EAV模型而非行模型:

  • 数据记录中的单个属性的数据类型不同(是/否,数值型;Yes/No,numerical value,string);采用行模型时一张表中很难存储属性的值。

  • 许多种类的数据必须表现出来,其数量可能出现波动。与此同时,即使不稀疏的属性,然每类数据都非常少。这种情况下,传统的数据模型将使成百的表却只有几行数据。

  • 在一定的环境中,其类别/类必须在动态创建,某些类在原型随后的周期中常常会被省略。

  • 某些类归类为混合型的类,这意味着一些类的属性是稀疏的,而其他属性则是非常稀少的。 在这种情况下,非稀疏属性存储在传统表中,而稀疏的属性存储在EAV或行建模的格式。 这些类通常会满足商业数据库应用的需要,所有产品将共享这些属性,如包装单位和单价。请注意,如果只有一两个混合类,EAV设计可能不值得。

实体、属性和值表示

实体

一个实体可以是任何条目,到目前为止,所看到的例子是销售事件实体、商人和产品实体。 EAV管理的实体是通过一个对象表,用以获取每个项目的共同数据,如名称、说明等。对象表中的每一实体必须具有唯一的标识符,而这通常是自动生成的。然后,该标识符在整个数据库作为外键。

采用EAV建模并不阻止使用传统的数据表来存贮单个对象的更多细节信息。这是在同一数据库模式(schema)内应用传统关系数据库模型和EAV模型的常见数据建模方法。

属性

属性存储在一个专门的属性表。本表的主键是用来作为跨数据库的参考。的属性表通常辅以多个元数据表,更详细地描述了一个属性。 此元数据信息通常用于自动化浏览和编辑数据的用户界面生成。元数据表可能包含如下型的信息部分:

  • 验证:验证元数据包括属性的数据类型、默认值、值数量的可能限制,以及可否为空(null)。

  • 展现:定义属性如何呈现给用户,是否为文本区域、下拉框或单选按钮/检验框(radio button/checkbox)组。

  • 分组:属性大多呈现在用户群体。 分组中的元数据定义了一个属性的显示方式,提出了属性的数量和什么样的字体和颜色类型使用的顺序。

  • 正常值范围:在某些情况下正常的值范围,可能会随性别、年龄有所不同,等等。

描述EAV模型值的最简单方法就是将其数据存储为一个字符串。但是,这种方法是相对低效的,因为做任何事与该值相关的事情是都需要进行数据类型转换。 此外,对存储为字符串的值创建的索引不允许针对数值型和日期型的搜索范围优化,这是采用混合数据类型的键-值对描述数据的公共问题。

为改善这种情况,EAV模型为每一数据类型建立单独的表。属性元数据标识正确的数据类型以及随后存储数据的EAV表。这种方法更有效,因为它允许在访问数据之前,缓存给定属性的元数据。

这种方法的主要缺点在一个属性的数据类型需要改变时是显而易见的,需要将数据从一张表重新分配到另一表中,这很不方便,可以通过存储过程来解决。

一般情况下,空值或不适用于此EAV模型。但某些情况下,存在记录缺失值的必要原因。 在这种情况下,解决方法是在表中添加缺失值的编码列,仅在该列的值为空(null)时其值非空。然后,此编码用于查找文字说明清单。

EAV模型的优/缺点

优点

EAV模型的主要优点是其灵活性

属性描述表不限制列的数量,这意味着每次新增属性不需要重新设计数据结构(schema);扩展数据库时,属性的数量可以垂直增加(每一新的参数在表中为一的记录),而无需改变数据结构。

事实上,EAV只处理非空属性意味着不需要为空值保留额外的存储空间。这使得EAV模型相当节省空间。

物理数据格式是非常干净,类似于XML,很容易将数据映射为XML格式,只需替换要开始和结束属性标签。

EAV模型可以极好地迅速扩展应用,因为它可以防止(属性)不断变化的后果。可以简单地记录任何结构的新数据,而不需要修改任何数据结构。

缺点

当考虑EAV时,确定数据是否稀疏和量大恒重要,因为采用不恰当的数据集时,EAV设计的复杂性超过了其优势所在。相对静态或简单数据选用传统的表结构更为合适。

相较于传统的数据结构,EAV的一个主要缺点是它在检索大容量数据时效率较低。在EAV模型中,数据更加分散,所以查询(select)一个完整实体的记录需要多个表连接。更重要的是,当EAV模型应用于大数据量时,对于同一组EAV建模的数据描述,需要短暂或永久地在列(column)和行之间进行转换。该操作易于出错且是CPU密集型的任务。

EAV模型的另一个局限性,需要制定额外的逻辑来完成传统数据结构(/模式)下自动进行的述务。但是,利用现有的EAV工具可以降低此类工作的成本。

最后,理解EAV模型确实需要时间。它有一个明确的学习曲线,使的初级开发人员在真正理解其概念前,需要为此付出更多的精力。

结论

应用实体-属性-值时,应考虑以下条件:

  • 数据是稀疏的、异构的,一个实体的属性范围较广,且常引入新的属性。

  • 类的数量非常大,有许多实例类,即使属性是非稀疏的。

  • 有许多混合类,既具有稀疏也具有非稀疏属性。通常情况下,并不是所有的数据类满足EAV建模的要求。

在生产环境中,往往采用混合模式(mixed schema),包括传统的关系、EAV或合适的混合方法。 但是,EAV建模,需要引入元数据来获取EAV的逻辑模型数据。 我们看到Magento,受EAV影响很大,其中各种不同的产品将有很不同的属性集, 是一个运用该模型的非常有效的好例证。本文希望揭示什么是EAV模型,以及如何、何时应用它才更重要。

实际案例

django-eav is a python project.

eav-model-pattern is a java project.