mysql - 我应该将 EAV 值放入数据类型表中吗?

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

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

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

任何人都可以指出是否应该将这些值放入自己的特定于数据类型的表中(例如 attribute_values_int,或作为通用 attribute_value 表中的列?由于性能原因,Magento 选择了特定于数据类型的值表。请参阅:http://blog.magestore.com/2012/03/23/magento-certificate-eav-model-concepts

谢谢。

最佳答案

坦率地说,最好的选择是“不是 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)

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

关于mysql - 我应该将 EAV 值放入数据类型表中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17649598/

相关文章:

java - 使用 JDBC 连接到 MySQL

mysql - 使用 HAProxy 负载保护多数据库 mariadb 集群

sql - 如何从 Postgresql 子查询中的同一个表中获取用户名而不是 id?

sql-server - 如何存储数据库之间共享的数据?

mysql - 我应该担心表中的 1B+ 行吗?

php - 我们如何获取重复日期的价格(总和),但在 mysql 中也需要?

PHP SQL 结果不会填充个人资料页面

java - 连接 Amazon RDS 上的顶级 PostgreSQL 9.3.1 时 Hibernate/JDBC 挂起

php - 为什么 PHP PDO DSN 是 MySQL 与 PostgreSQL 的不同格式?

mysql - 处理同一个表上的多个多对多关系?