1.
Magento的表有三百多张,以实体、属性、值(EAV)的数据库结构难以掌握,加上缺少有关EAV的文档,以至许多人不知道这种EAV方式的好处以及 它对magento来说的重要性,在这里作为一名magento开发者,让我们来了解下,它是如何工作的并且对我们有什么好处。
什么是EAV呢?
EAV是实体(Entity)、属性(Attribute)、值(Value)的意思,接下来来看看每一部分以便更好的理解它。
实体(Entity)
实体指的是magento的数据对象,如产品、分类目录、客户、订单等,每一个实体在数据库中都对应着一条实体记录。
属性(Attribute)
属性是指跟实体相关的一些性质数据,如产品实体有名称、价格、状态等。
值(Value)
值是最容易理解的了,就是指属性的值了。
EAV是怎么工作的呢?
一直以来,数据库其实很简单的,比如我们现在要设计一个商城,需要有一张产品表,包括所有产品的信息,另一张表包括分类信息,也许还要一张表来连接这两 张,这样很容易理解吧,然而magento却不一样,它跟产品以及分类有关的表有40多张,要想知道为什么,让我们来看下产品表。
不像其它的商城那样,所有的产品信息在一张表里,magento把产品信息分离在子表中,最顶上的表是catalog_product_entity,如 果你看过这张表,你肯定发现了,它只包括产品的一些基础信息,除了SKU,其它你看不到任何有用的信息,幸运地是使用这张表你将可以从属性和值表中看到完 整的产品记录。
让我们开始新建一条完整的产品记录,你需要将属性与我们的实体表相关联,做这之前先看下表eav_attribute,这张表在magento里为所有不 同的实体存储了所有的属性,打开表,你会看到里面有好几百条不同属性的记录,为什么有些名称还是一样的呢?困惑吧?magento是如何辨别的呢?很快你 就会注意到entity_type_id,每一个实体都会有一个entity_type_id,为了找出来,那就再回来 catalog_product_entity表,看entity_type_id字段,你会发现所有的记录值都是10,如果你有去看 catalog_category_entity,你将会看到一个不同的entity_type_id值。根据这个值和attribute code你就可以找到所有产品的属性,当然也可以所有其它实体的属性了。
思考下下面的查询:
# 找出所有产品的属性
SELECT attribute_code FROM eav_attribute WHERE entity_type_id = 10;
# 找出单个产品的属性
SELECT attribute_code FROM eav_attribute WHERE entity_type_id = 10 AND attribute_code = 'name';
你得到属性和实体了吧。接下来了解下值,值被分离在不同的表中,让我们看下所有前缀是catalog_product_entity的表,值是根据它们的 类型来分的,例如,所有的价格以及其它decimal属性的会存储在表catalog_product_entity_decimal中,另外所有文本类 型数据会存储在catalog_product_varchar中,需要指出的是每个属性存储的表,magento在eav_attribute表中使用 字段backend_type记录,如果你运行以下查询,你将可以找到产品属性'name’的backend type。
SELECT attribute_code, backend_type FROM eav_attribute WHERE entity_type_id = 4 AND attribute_code = 'name';
希望以上的查询返回的是varchar,这就是name的正确类型啦,基于以上,我们可以知道namer值被存储在表catalog_product_entity_varchar中,你认为下面的查询会存储在哪呢?想一想,然后copy it看下你对了没。
SELECT e.entity_id AS product_id, var.value AS product_name FROM catalog_product_entity e, eav_attribute eav, catalog_product_entity_varchar varWHERE e.entity_type_id = eav.entity_type_id AND eav.attribute_code = 'name' AND eav.attribute_id = var.attribute_id AND var.entity_id = e.entity_id
为什么使用EAV呢?
使用EAV是因为它相比其它普通的数据库结构要更容易扩展。开发者不用编辑核心数据库结构就可以为任何实体添加属性,并且当自定义的属性被添加后,不需要添加任何逻辑让magento保存它,因为这些在模型中都已经存在了,只要数据和属性创建后,模型就会保存了。
EAV有什么缺点呢?
最主要的就是它的速度了,由于实体数据都是碎片式的,建立一个完整的实体记录需要许多表联合查询。幸运地是Varien团队开发了个优秀的缓存系统,允许开发者缓存那些不常改变的信息。
另一个问题就是学习的风险,很多开发人员学习到半途就放弃了,对于这还真没有什么捷径,希望我们共同征服它吧!
总结
实体、属性、值是很好的一种数据库结构,也是学习magento很关键的一部分,因此对于开发者来说,明白它是如何工作的就显的十分重要了。
欢迎一起交流,祝你好运!
2.
EAV的最简单实现可能只有三个表:实体,属性和值。如此设置的示例如下所示:
![](http://image71.360doc.cn/DownloadImg/2014/03/1617/39944418_1.jpg)
然而,在这种实现中,缺失了元数据信息,不论何种数据类型,所有的值都存为varchar。作为对这一方法的衍生,可以另外选择一个强类型的实现方法,其中一个给定数据类型的值存储为特定类型表的数据记录。下述模式(schema)例子所示,其中包括元数据信息,如前文所讨论。
![](http://image71.360doc.cn/DownloadImg/2014/03/1617/39944418_2.jpg)
Magento采用EAV模型(Magento Uses The EAV Model)
在开源和php社区,最著名的EAV实现是Magento,一个电子商务平台。首先来看看Magento的数据库模式(Magento database schema)。虽然一开始显得复杂AA3 颐侵鸩嚼翠 馈 /P>
正如之前提到的,实体可以是任何条目或事件。Magento中包含多个实体,例如:客户,订单,发票和产品。出于本文的目的,将用产品实体来解释EAV的实现。产品的主表为catalog_product_entity。但是,您可能会感到惊讶,只保存了几类的信息,如实体类型,型号(SKU)以及产品创建时间。
为建立一个完整的产品记录,需要找到它的属性,然后找到每一属性的值。在catalog_product_entity表中,会发现 entity_type_id列,用来在整个数据库中标识实体的类型。基于实体的类型,可以通过查找eav_attribute来找到要设置产品的那一属性。此表记录了Magento所有实体的全部属性,也包含每一记录的元信息,如数据类型、前端细节等;就产品而言,实体类型ID设置为4(类型在 eav_entity_type表中列出),查询欲设置的所有产品属性,简单操作如下:
SELECT*FROMeav_attribute WHEREentity_type_id =4;
属性的名称被记录为attribute_code,元数据信息中,一个重要的列为backend_type,这表明一属性为何种数据类型,该属性的值存在何处。Magento的允许下列数据类型:
static datetime decimal int text varchar正如前面所述,值可以基于其数据类型存储在多个表中。检查一特定属性,可以使用如下查询:
SELECT*FROMeav_attribute WHEREentity_type_id =4ANDattribute_code ='name';
上述查询运行后,可以看到,属性“name”的数据类型为varchar,产品属性的值跨多个表存储:
catalog_product_entity_datetime, catalog_product_entity_decimal, catalog_product_entity_int, catalog_product_entity_text, catalog_product_entity_varchar。这些表说明了EAV模型中不同数据类型的存储方式。
为获得所有的产品,可使用的查询列表如下:
SELECT cpe.entity_id,value ASname FROM catalog_product_entity cpe
INNER JOINeav_attribute ea ON cpe.entity_type_id =ea.entity_type_id
INNER JOINcatalog_product_entity_varchar cpev ON ea.attribute_id =cpev.attribute_id AND cpe.entity_id =cpev.entity_id
WHERE ea.attribute_code ='name'
这个概念很简单,一旦你知道从哪里开始以及如何查找表中的下一个层次。所有其他实体遵循同样的原则:对于感兴趣的对象先找到实体类型ID,然后基于该ID从eav_attribute中获得所有属性,最后,基于属性的数据类型,从不同的表中查询每一属性的值。
EAV模型的优/缺点(Advantages and Disadvantages of the EAV Model)
EAV模型的主要优点是其灵活性。属性描述表不限制列的数量,这意味着每次新增属性不需要重新设计数据结构(schema);扩展数据库时,属性的数量可以垂直增加(每一新的参数在表中为一的记录),而无需改变数据结构。
事实上,EAV只处理非空属性意味着不需要为空值保留额外的存储空间。这使得EAV模型相当节省空间。
物理数据格式是非常干净,类似于XML,很容易将数据映射为XML格式,只需替换要开始和结束属性标签。
EAV模型可以极好地迅速扩展应用,因为它可以防止(属性)不断变化的后果。可以简单地记录任何结构的新数据,而不需要修改任何数据结构。
当考虑EAV时,确定数据是否稀疏和量大恒重要,因为采用不恰当的数据集时,EAV设计的复杂性超过了其优势所在。相对静态或简单数据选用传统的表结构更为合适。
相较于传统的数据结构,EAV的一个主要缺点是它在检索大容量数据时效率较低。在EAV模型中,数据更加分散,所以查询(select)一个完整实体的记录需要多个表连接。更重要的是,当EAV模型应用于大数据量时,对于同一组EAV建模的数据描述,需要短暂或永久地在列(column)和行之间进行转换。该操作易于出错且是CPU密集型的任务。
EAV模型的另一个局限性,需要制定额外的逻辑来完成传统数据结构(/模式)下自动进行的述务。但是,利用现有的EAV工具可以降低此类工作的成本。
最后,理解EAV模型确实需要时间。它有一个明确的学习曲线,使的初级开发人员在真正理解其概念前,需要为此付出更多的精力。
结论(Conclusion)
应用实体-属性-值时,应考虑以下条件:
数据是稀疏的、异构的,一个实体的属性范围较广,且常引入新的属性。 类的数量非常大,有许多实例类,即使属性是非稀疏的。 有许多混合类,既具有稀疏也具有非稀疏属性。通常情况下,并不是所有的数据类满足EAV建模的要求。在生产环境中,往往采用混合模式(mixed schema),包括传统的关系、EAV或合适的混合方法。但是,EAV建模,需要引入元数据来获取EAV的逻辑模型数据。我们看到Magento,受 EAV影响很大,其中各种不同的产品将有很不同的属性集,是一个运用该模型的非常有效的好例证。本文希望揭示什么是EAV模型,以及如何、何时应用它才更重要。如果您有更多应用EAV模型的例子,或有任何疑问,请作评论!