我们目前正在构建一个允许我们为硬件创建配置文件的系统。每个配置文件都存在一些不同的属性,这些属性都通过UI动态添加到配置文件中。每个属性可以是不同的类型(字符串,整数,文本,......)
如何在关系数据库中最有效地存储这些属性?
我已经阅读了Storing diverse value types in a database,我对那里的单一答案感到很着迷,但我完全不相信这是理想的解决方案。与其他解决方案相比,是否有使用单独表格式方法的优点/缺点?任何人都有这方面的真实世界经验和思想分享最好的方法吗?
答案 0 :(得分:3)
使用data type text列。
PostgreSQL中的每种数据类型都有文本表示 - 否则普通的pg_dump会失败。此外,用户如何首先输入值?
我已经有几个这样的用例了几年了。没问题。 您可以另外存储实际数据类型,并在需要时转换文本表示。
一个缺点可能是某些类型的文本表示的盘上空间会更高。但是多列/表的开销很容易弥补这一点。
您可能也对新数据类型hstore
in PostgreSQL 9.0感兴趣。 (该模块已存在更长时间,但在9.0中有很大改进。)
PostgreSQL在索引方面非常通用。我会在评论中用partial index on an expression解决一个案例:
CREATE INDEX tbl_col_propx_idx ON tbl (cast(col AS int))
WHERE prop_type_id = 23; -- 23 signifying "propertyX"
prop_type_id
将是查找表的外键(引用外键):
CREATE TABLE prop_type(
prop_type_id int PRIMARY KEY,
prop_type text NOT NULL);
prop_type_id
也可以是enum
type。在最新版本中处理enums has been much improved。
然后像这样的查询会很快变亮:
SELECT *
FROM tbl
WHERE prop_type_id = 23 -- 23 signifying "propertyX"
AND col::int BETWEEN 50 AND 100
此外,如果您尝试输入与该类型不匹配的字符串,此类索引将自动验证数据类型并抛出错误。
答案 1 :(得分:1)
我首选的方法是单个表,其中键和值都是varchar和/或文本。
我能想到的评论中每个类型表的唯一一大缺点就是很难用这个键值条目所属的实体来约束密钥的唯一性。
表继承(但仍然使用table-per-type)将是另一种方式,恕我直言,它是残酷的类型安全并符合postgres和ORM概念:
CREATE TABLE key_values(user_id integer references users(id), key varchar(255), type varchar(255), CONSTRAINT UNIQUE(user_id, key));
CREATE TABLE key_values_int(value integer) INHERITS (key_values);
CREATE TABLE key_values_string(value varchar(255)) INHERITS (key_values);
and so on...
这完美映射到JPA。