添加列与添加行 - 这提供了更好的性能?

时间:2014-08-11 20:40:59

标签: sql postgresql database-design entity-attribute-value

搜索和搜索。不知道如何使用Explain / Analyze来回答这个问题,而不构建真正庞大的测试表,而且我没有时间或时间去追求它。当然有人可以自信地回答这个可能简单的问题,并节省我数小时的测试结果。

我有一张看起来像这样的表:

id | destination_id | key | value | json_profile_data | deleted_bool | deleted_timestamp

密钥和值是表的原始用法,但我们最近开始存储json数组,现在键/值字段未使用。我想在此记录ID中添加3个新位数据。我的直觉是在3个新字段的每一行中创建新列,但我的同事希望使用键/值cols使用相同的destination_id添加信息。

我的建议意味着表格中的行数更少,如下所示:

id | destination_id | key | value | json_profile_data | claim_code | claim_date | claim_approved_bool | deleted_bool | deleted_timestamp

HIS解决方案是添加新行,使用键/值cols在这些新行上插入与其父行相同的destination_id的三个新信息位。

id | destination_id | null                | null  | json_profile_data | deleted_bool | deleted_timestamp
id | destination_id | claim_code          | value | null              | deleted_bool | deleted_timestamp
id | destination_id | claim_date          | value | null              | deleted_bool | deleted_timestamp
id | destination_id | claim_approved_bool | value | null              | deleted_bool | deleted_timestamp

他的解决方案为每个destination_id创建了4行,我在现有行上为给定的destination_id创建了3个新列。

对于此表的选择,哪个性能更高?或者重要吗?我希望我以一种明确的方式写出来。如果需要更详细的说明,请告诉我。

3 个答案:

答案 0 :(得分:1)

与大多数数据库一样,答案是"它取决于"。特别是,主要取决于需要返回什么结果集,指定了什么谓词,索引可用,基数等。

说到这一点,一般来说,向表中添加列可能会比添加行提供更好的性能。

更重要的问题(我认为)是插入/更新/删除操作的设计。

原始表看起来像是EAV(实体属性值)模型的实现;当结果需要被转动"并以不同的格式返回时,针对EAV的查询会变得非常复杂;或者当我们有多个属性的谓词时。

为了坚持使用EAV模型,我们会在表格中添加行,并研究处理该行所需的更复杂的SQL。

但如果改进性能是目标,我们可能完全避免使用EAV模型,只将属性存储为列。这是传统的关系数据库模型:每一行代表一个"实体" (即可以唯一标识的人,地点,事物,概念或事件,我们需要存储信息),每列代表一个"属性",一条关于实体的信息。

答案 1 :(得分:0)

正如你所说,你必须用实际的数据来尝试这一点才能凭经验看待它,但毫无疑问,“添加列”的方法会更高效。另一种方法需要四个连接,这几乎肯定会减慢速度。

答案 2 :(得分:0)

您的员工建议 EAV 存储空间。有关dba.SE的相关问题的详细信息:

其余部分用于 Postgres ,仅适用于部分MySQL 您已经拥有 json列,这是该问题的明显第三解决方案,但您似乎都没有考虑过这一点?甚至可能只是添加到json列中(那是不是我通常会做的事情。)实际上,如果你走这条路线,请考虑即将发布的Postgres 9.4中的新jsonb

但是,只要我们谈论的是这三个专栏(而不是每n周一次的新专栏),您的方法就会赢得任何可能的方面,也是一个长镜头。其他列更便宜。即使它们大多数时间都是NULL,因为NULL存储非常便宜:

存储容量是性能的主要贡献因素。

任何一种方法都可以编入索引。对于EAV存储,您可以使用partial indexes。为了优化这一点,需要了解典型的查询,访问模式,要求和优先级。您的方法通常更易于管理。

您的方法会松散的明显方面:

  • 如果有新的列的变量(但未知),则需要动态添加。使用EAV方法更加简单。

  • 如果您只有(一个)新列有很多更新。对于小的单独行,这会更便宜。

最近的相关答案讨论了表中的许多列,以及用于EAV存储通常需要交叉制表的代码: