坦率地说,最好的选择是 “不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)
在这种情况下,零位不会由于对齐要求增加任何空间可言,有可能。
纠正我,如果我错了,但如果你发布一个链接,说明*性能*原因magento使用类型特定的表..不是明显的答案吗?如果您不使用特定于类型的表格,则最终将所有内容添加到varchar/text列。如果你这样做,你需要一个元数据表来解释属性的存储位置(在int,float,char表中)。 –
@ N.B。感谢您的评论,但我也可以创建具有不同列的值表(value_int,value_datetime等)。我希望你能解释为什么特定数据类型选项会带来更好的性能,至少在Magento的情况下? – Hans
因为如果使用特定于数据类型的表,并且可以将某些数据类型表编入索引,那么将节省更多空间。这不是一个性能增益,因为它可以放宽需要担心属性是否适合值列。想象一下,有一个EAV设计有1个值表,并且您正在存储可以是单个1位数字或大量文本的数据。你被迫使用'text'类型,所以你可以存储任何东西。或者你可以创建一个特定类型的表,不用担心“全部捕捉”表,它是存储值的列。 –