【问题标题】:Is there a disadvantage to having large columns in your database?数据库中有大列有什么缺点吗?
【发布时间】:2012-10-10 04:46:37
【问题描述】:

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

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

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

【问题讨论】:

  • 什么意思:“我刚刚将用户完成的每种问题的用户统计信息存储在用户表中的序列化哈希中。” 哈希是一个不可逆的过程 - 您不能仅从哈希中恢复原始数据。您的意思是:“序列化结果的字节数组”?
  • 我说的是 ruby​​ 哈希 - 就像在哈希表中一样,而不是哈希函数。抱歉,如果不清楚,显然哈希函数的意义在于它们是不可逆的。
  • 感谢您的回答!对于任何以我的知识水平进入此问题的人,我将总结一下我从每个人的 cmets 中学到的东西:(1)大列意味着您有很多无法查询的属性(例如,我无法查询所有用户) > 50% 的问题类型) - 违反原子性。 (2) 选择时整行都加载到内存中,因此当您不需要该列或选择许多用户时会产生很多开销。 (3) 如果您不需要查询数据,而当您需要其中的任何一个时,您需要大部分数据,那么大列还不错。

标签: database database-design relational-database database-schema


【解决方案1】:

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

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

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

【讨论】:

  • +1 仅用于 您可以(并且应该) 规范化您的数据库..(顺便说一句,即使模型发生变化,它也总是可以的;它只需要好的工具。)
【解决方案2】:

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

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

【讨论】:

  • 只是强调一下:OODBMS反对规范化 - 至少在这个级别。也就是说,它们可能违反了一些更严格的范式,但它们规定“单列中的数据团”,这听起来像是这个问题。
  • 我没有说 ORDBMS 不反对规范化。我说权衡是不同的。例如,在某些情况下,嵌套存储/非 1nf 设计在 ORDBMS 中可能很有用,但您不能在纯 RDBMS 中真正合理地使用它们。事实上,在这个层面上,这有助于理解。例如,当您可以将 XML 文档存储在您的数据库中,并将 xpath 操作集成到您的 SQL 查询中时,您对序列化数据的数据组织选择就大不相同了。
  • 感谢您回答我的问题 - 既然您提到了它,那么必须为我从数据库中获得的每个用户加载所有这些数据似乎是一个劣势。幸运的是,现在我每次选择多个用户时都需要所有这些数据。
【解决方案3】:

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

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

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


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

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

【讨论】:

  • 目前我确实在每次使用它们时都在使用大多数列,尽管不是每次访问用户时。这可能会随着网站使用量的增加而改变,所以我会牢记垂直分区的想法,尽管我相信我最终只想将统计数据移到他们自己的表中。
【解决方案4】:

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

【讨论】:

    猜你喜欢
    • 2012-08-29
    • 2013-02-19
    • 2011-08-14
    • 2019-09-15
    • 2017-05-15
    • 2011-04-26
    • 2011-02-28
    • 1970-01-01
    • 2019-09-15
    相关资源
    最近更新 更多