我应该将EAV值放在数据类型表中吗?

时间:2013-07-15 08:15:47

标签: mysql postgresql database-design entity-attribute-value

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

在我的情况下,商店,客户,供应商和仓库的所有属性都可以定义为列,因为它们不会随着时间的推移而发生太大变化。然而,产品具有无限量的属性,因此我想将这些数据放入EAV模型中。

是否可以指出值是否应该放在他们自己的数据类型特定的表中(例如attribute_values_int,或者作为泛型attribute_value表中的列?由于性能原因,Magento选择了特定于数据类型的值表。请参阅:{ {3}}

感谢。

1 个答案:

答案 0 :(得分:2)

坦率地说,最好的选择是“不是EAV”。请查看使用hstore字段,XMLjson

在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)

在这种情况下,空位图根本不会添加任何空间,可能是由于对齐要求。