1

我的数据库存储有关各种问题的用户统计信息。没有问题类型表,因此我没有在问题类型上使用连接表,而是将用户已完成的每种问题类型的用户统计信息存储在用户表中的序列化哈希映射中。显然,这导致了一些相当大小的用户行——我自己的用户的序列化统计信息大约是 950 个字符,我可以想象它们很容易增长到高级用户的 5 kb。

我从来没有在任何一本书中读过这么大的专栏的例子。我的表中有这么大/可变的列会极大地阻碍性能吗?我应该为问题类型添加一个表格,并使用户统计信息也成为一个单独的表格吗?

如果相关的话,我目前正在使用 PostgreSQL。

4

4 回答 4

3

我已经在 ProcessMaker 等系统上看到过这种序列化方法,它是一个 Web 工作流和 BPM 应用程序,并以序列化方式存储其数据。它的性能相当不错,但是基于这些数据构建报告确实很棘手。

您可以(并且应该)规范化您的数据库,如果您的信息模型不经常更改,这是可以的。

否则,您可能想尝试非关系型数据库,如 RavenDB、MongoDB 等。

于 2012-10-10T05:07:39.733 回答
2

最大的缺点与 select *. 如果您有一个特定的字段列表,您可能不会遇到大问题,但是使用带有很多 TOASTed 列的 select *,您有很多额外的随机磁盘 I/O,除非所有内容都适合内存。选择更少的列会使事情变得更好。

在像 PostgreSQL 这样的对象关系数据库中,数据库规范化带来了与纯关系模型不同的权衡。总的来说,这仍然是一件好事(正如我所说,在你的数据库中执行 OR 操作之前,尽可能将关系模型推到最舒适的位置),但你可能认为它不是绝对必要的纯粹的关系数据库。此外,您可以添加函数来使用正则表达式处理该数据、从 JSON 中提取元素等,并将这些元素拉回您的关系查询中。因此,对于无法正常化的数据,大的无定形“docdb”字段并不是什么大问题。

于 2012-10-10T08:37:32.447 回答
2

取决于您需要的主要查询:

  • 如果您需要选择所有(或大部分)列的查询,那么这是最佳设计。
  • 但是,如果您主要在列的子集上进行选择,那么可能值得尝试对表进行“垂直分区” 1,这样您就可以避免“不需要”列的 I/O 并提高缓存效率。2

当然,所有这一切都是假设序列化数据从数据库的角度表现为“黑匣子”。如果您需要以某种方式搜索或约束该数据,那么仅存储一个虚拟字节数组将违反原子性原则,因此违反 1NF,因此您需要考虑规范化您的数据......


1即将很少使用的列移动到第二个表中,该表与原始表的关系为 1:1。如果您使用的是 BLOB,则可以通过声明 BLOB 的哪一部分应保持“内联”来实现类似的效果 - 超出该限制的任何 BLOB 的其余部分将存储到与表的“核心”分开的一组页面中“页。

2 DBMS 通常在页面级别实现缓存,因此行越宽,适合磁盘上单个页面的行越少,因此适合缓存中的单个页面。

于 2012-10-10T14:40:54.137 回答
1

您不能在序列化数组中搜索。

于 2012-10-10T04:54:02.340 回答