我正在为商店、产品、客户、供应商和仓库等实体设计一个数据库。该数据库将作为不同实体店的在线交易系统。
在我的例子中,商店、客户、供应商和仓库的所有属性都可以定义为列,因为它们不会随着时间的推移而发生太大变化。然而,产品具有无限数量的属性,因此我想将这些数据放入 EAV 模型中。
任何人都可以指出是否应该将这些值放入自己的特定于数据类型的表中(例如 attribute_values_int,或作为通用 attribute_value 表中的列?由于性能原因,Magento 选择了特定于数据类型的值表。请参阅:http://blog.magestore.com/2012/03/23/magento-certificate-eav-model-concepts
谢谢。
最佳答案
坦率地说,最好的选择是“不是 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)
在这种情况下,空位图根本不会添加任何空间,可能是由于对齐要求。
关于mysql - 我应该将 EAV 值放入数据类型表中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17649598/