Postgres 9.4+:JSONB 而不是 EAV

cou*_*sej 6 postgresql database-design eav json

我正在想办法构建一个新的 PostgreSQL 数据库,我很好奇是否可以使用 JSONB 列而不是 EAV 模型来存储实体的属性。这似乎是一种灵活的方式来存储这些东西。

在 EAV 情况下,我将有 3 个表:

materials (mat_id, mat_name, mat_descr)
material_properties (prop_id, prop_name, prop_desc)
material_property_values (mat_id, prop_id, val)
Run Code Online (Sandbox Code Playgroud)

每种材料都可以有一组不同的属性。

有什么原因我不应该只mat_props JSONB在我的materials表中添加一列,并将所有属性存储在那里{"name":"value"}?这样,将属性作为列进行查询将非常简单:

SELECT mat_name, mat_props->'name' as propval FROM materials
Run Code Online (Sandbox Code Playgroud)

而不是连接或子选择。

另外,我是否可以在materials表中添加此列,或者将其保存在单独的表中是否会更高效:

material_properties (mat_id, properties JSONB)
Run Code Online (Sandbox Code Playgroud)

Dan*_*ité 5

JSONB 可能易于阅读,但写入起来很复杂且效率低下。

例如,请参阅此问题:PostgreSQL update and delete property from JSONB column,了解它的外观。这比使用经典 EAV 表进行更新/删除要困难一个数量级。

可能当您编写了附加/合并/删除键/值对的部分时,基于 JSON 的设计的优雅或简单性似乎就不那么明显了。至于性能,我打赌它会更糟。

在存储级别,对 JSON 结构中的一个属性的任何写入都需要重写整个列(实际上是包含行),其成本与所有属性都发生更改的成本相同。这在 I/O 大小和真空压力方面不是最佳的。

在另一个问题中提到了这个问题,还有更多的链接和参考:

如何在 Postgres 9.4 中对 JSONB 类型的列执行更新操作

正在进行的工作是为程序员简化 JSONB 更新。jsonbx提供了有助于 9.4 的函数和运算符;据推测,这些将在未来版本中集成到 PostgreSQL 核心中。但是在大型 JSON 对象中进行小型更新的大型 I/O 成本仍将存在。

jsonbx 在最近的 PG 会议上展示(youtube 链接):

jsonb 的更新和删除操作(第 1 部分,共 2 部分)
jsonb 的更新和删除操作(第 2 部分,共 2 部分)