2013-07-15 24 views
0

我正在为商店,产品,客户,供应商和仓库等实体设计数据库。该数据库将用作不同实体商店中的在线交易系统。我应该将EAV值放在数据类型表中吗?

就我而言,商店,客户,供应商和仓库的所有属性都可以定义为列,因为它们不会随时间变化很多。然而,产品具有无限的属性,所以我想将这些数据放在EAV模型中。

可有人指出,如果值应在自己特定的数据类型,表把(如attribute_values_int,或由于性能原因,在通用ATTRIBUTE_VALUE表列的Magento已经选择特定的数据类型,值表见?: http://blog.magestore.com/2012/03/23/magento-certificate-eav-model-concepts

感谢。

+0

纠正我,如果我错了,但如果你发布一个链接,说明*性能*原因magento使用类型特定的表..不是明显的答案吗?如果您不使用特定于类型的表格,则最终将所有内容添加到varchar/text列。如果你这样做,你需要一个元数据表来解释属性的存储位置(在int,float,char表中)。 –

+0

@ N.B。感谢您的评论,但我也可以创建具有不同列的值表(value_int,value_datetime等)。我希望你能解释为什么特定数据类型选项会带来更好的性能,至少在Magento的情况下? – Hans

+0

因为如果使用特定于数据类型的表,并且可以将某些数据类型表编入索引,那么将节省更多空间。这不是一个性能增益,因为它可以放宽需要担心属性是否适合值列。想象一下,有一个EAV设计有1个值表,并且您正在存储可以是单个1位数字或大量文本的数据。你被迫使用'text'类型,所以你可以存储任何东西。或者你可以创建一个特定类型的表,不用担心“全部捕捉”表,它是存储值的列。 –

回答

2

坦率地说,最好的选择是 “不EAV”。考虑使用hstore领域,XML,或json

在PostgreSQL没有性能优势,使用每数据类型表。 NULL值存储在一个紧凑的NULL位图中,所以它与你是否有像(NULL, NULL, NULL, 42, NULL, NULL)(42)这样的元组没有多大区别。

这也允许你添加CHECK约束实施,确切地说一个字段必须是非NULL,所以你不会得到不同类型的多个值。

演示:

regress=> CREATE TABLE eav_ugh (
    entity_id integer, 
    int_value integer, 
    numeric_value numeric, 
    text_value text, 
    timestamp_value timestamp with time zone, 
    CONSTRAINT only_one_non_null CHECK (
      (int_value IS NOT NULL AND numeric_value IS NULL AND text_value IS NULL AND timestamp_value IS NULL) OR 
      (int_value IS NULL AND numeric_value IS NOT NULL AND text_value IS NULL AND timestamp_value IS NULL) OR 
      (int_value IS NULL AND numeric_value IS NULL AND text_value IS NOT NULL AND timestamp_value IS NULL) OR 
      (int_value IS NULL AND numeric_value IS NULL AND text_value IS NULL AND timestamp_value IS NOT NULL) 
    ) 
); 
CREATE TABLE 
regress=> insert into eav_ugh (entity_id, numeric_value) select x, x from generate_series(1,5000) x; 
INSERT 0 5000 
regress=> select pg_relation_size('eav_ugh');           
pg_relation_size 
------------------ 
      229376 
(1 row) 

regress=> CREATE TABLE no_null_cols(entity_id integer, numeric_value numeric); 
CREATE TABLE 
regress=> insert into no_null_cols (entity_id, numeric_value) select x, x from generate_series(1,5000) x; 
INSERT 0 5000 
regress=> select pg_relation_size('no_null_cols'); 
pg_relation_size 
------------------ 
      229376 
(1 row) 

regress=> SELECT sum(pg_column_size(eav_ugh)) FROM eav_ugh; 
    sum 
-------- 
164997 
(1 row) 

regress=> SELECT sum(pg_column_size(no_null_cols)) FROM no_null_cols; 
    sum 
-------- 
164997 
(1 row) 

在这种情况下,零位不会由于对齐要求增加任何空间可言,有可能。

+0

谢谢指出克雷格。将所有值列放在单个表中时,是否可以在不检查数据类型的情况下执行select?这样数据库返回非空列值?如果可能的话,我可以想象这比先检查数据类型要快得多。当然,我们会在选择包含日期计算的行时遇到问题。 – Hans

+0

@Hans:不,它不是;这是我讨厌EAV并且更喜欢使用诸如hstore,json或xml字段之类的许多原因之一。 –

+0

好吧,我必须研究hstore,xml和json的可能性,因为我的属性链接到配置表。我不知道这是否可能。 – Hans

相关问题