【问题标题】:Disadvantages of table with too many columns表列过多的缺点
【发布时间】:2016-10-24 06:17:36
【问题描述】:

我有一些数据需要放入 PostgreSQL 数据库。这些数据与学校有关。所以有很多与学校相关的属性,主要是小整数、浮点数或小文本。并且所有数据每年都在变化。所以我正在创建一个名为YearlyData 的实体并将属性放在那里。但问题是,属性的​​数量在 50-60 左右。现在这些不能被规范化,因为它们是学校本身的简单属性。所以我在道德上不能将它们分成表格。但我不确定这是否会影响我的表现。

我可以尝试对这些数据进行分类并将它们放在单独的表中,并从YearlyData 表中指向它们。但是,我猜想尝试使用 20-30 多个参数搜索学校会导致大量的连接。我也不确定这是否会影响我的表现。

有什么专家建议吗?

【问题讨论】:

  • 我不认为 50-60 列会导致问题,除非它们是非常宽的列,例如大量文本和 blob 数据。我们在谈论什么样的数据?如果它主要是整数、日期等,那么它可能没问题。
  • 是的。主要是整数、浮点数或小文本。
  • 应该没问题,很有可能。当然,您可以通过测试获得实际指标。创建表,用大量随机垃圾数据填充它,在应用程序中运行一些场景并测量性能。此外,您希望该表有多少条记录?索引和优化将在某个时候发挥作用,如果有大量数据,那么将其中一些数据分解为针对搜索优化的表可能是有意义的。
  • 目前大约有 100,000 条记录。我真的没有那么多数据的经验,所以有疑问。我想我能做的最好的就是你说的。测试一下。
  • 测试它永远是最好的信息来源。 100,000 条记录并不是真正的 很多 数据,所以这可能会很好。但是,如果您最终在其中的许多列上放置了大量索引,那么您可能会开始获得性能收益递减。此时,您可能需要将其分解为几个表,其中针对具有特定索引的搜索优化表运行搜索,并将结果与​​其他表连接以获取剩余数据。这是需要考虑的事情,但在有真正的指标证明之前没有必要。

标签: postgresql database-design


【解决方案1】:

这里有几点需要考虑:

  • 属性列表是否随时间显着变化
  • 属性列表是否需要自定义用户定义属性
  • 不同学校是否有不同的属性(即许多属性只适用于一所或几所学校)?

如果其中任何一个属实,您可能会考虑使用属性存储方法like EAV, hstore, json fields, xml fields, etc

如果不是 - 如果您有一个相当静态的属性列表,其中大多数属性对大多数行都有意义 - 那么将它们作为 60 个单独的列并没有真正的问题。为通常搜索的属性集添加索引会更容易,包括部分索引和复合索引等,并且搜索 - 特别是针对许多不同属性的搜索 - 将快得多

另见:Database design - should I use 30 columns or 1 column with all data in form of JSON/XML?

您还可以选择一种折衷方案:一个主表,其中包含您经常查找的最重要的详细信息,以及用于属性逻辑分组的侧表。说:

yearly_summary (
    yearly_summary_id serial primary key,
    school_id integer,
    total_students integer,
    ...
) 

yearly_student_stats(
    yearly_summary_id integer primary key references yearly_summary(yearly_summy_id) on delete cascade,
    ...
)

等等。 integer primary key 也是 foreign key 表示您与另一个表具有强制的 1:1(可选)关系。如果您有一些属性的逻辑分组可以聚集到边表中,这种方法会很有用。

如果更多的思考并没有揭示出正常化有意义的事情,我也会感到惊讶。您有year7_blahyear8_blahyear9_blah 等列吗?如果是这样:标准化的绝佳候选者。

【讨论】:

  • 我目前正在使用许多列进行测试。做了一些逻辑分组。如果成功了,我想我会同意的。不,属性就像有has_computersnumber_of_computernumber_of_boys,等等。我确信我可以将它们分成更合乎逻辑的组,但这并不是真正的正常化,对吧?
  • @Bibhas 这并不是真正的规范化,但数据库工作并不总是关于纯度,有时它是为了性能、客户要求和现实世界的实施限制而妥协。在这种情况下,“纯粹”的方式听起来像是一张大桌子,如果您不打算一直添加属性或拥有用户定义的属性,那可能就是我会这样做的方式。如果我在跟踪过程中发现性能问题,我会在需要时将其拆分为子表。
  • 我想我明白了。谢谢。
  • 只是问,在这种情况下使用 NoSQL DBMS 有什么好处吗?
  • @Bibhas 当然,也有缺点。选择你的毒药。无论您选择哪种样式,您都放弃了很多功能来获得具有更动态模式的简化功能集。有些工作是合适的选择,但我很难想象这是其中之一。
【解决方案2】:

PostgreSQL 将行存储在大小为 8kb 的所谓数据页上。您可以将这些视为具有有限大小限制的存储桶。宽行的缺点是数据库可以在数据页上容纳较少的行。数据库引擎从一页带回 1,000 行比带回分布在多个页面上的 1,000 行要快。在这种情况下,一次读取与 1,000 次读取相比,磁盘 IO 是您的敌人。这是要注意不要避免的事情。通常需要宽桌子,您可以忍受开销。在您的情况下,您将大致每行使用 240 个字节(每个整数 4 个字节 * 60 行)。

【讨论】:

  • 你的意思是240字节吗?键行表是存储数据的好主意。但我需要对它们执行繁重的查询。你是怎么处理的?这样做的关键和价值在哪里?
  • 这种技术被称为"Entity Attribute Value",通常被认为是一种 DB 反模式甚至是性能定时炸弹。后者是因为在测试期间(通常使用小数据集)一切都很好,生产 start 很好(小表,一个父级的所有元组都在同一页面中......)但严重退化在将来。到那时,桌子已经很大,可以进行常规的重组工作(由于时间限制)。
  • 当您尝试对多个属性进行条件查询时,它会很快变得丑陋。你会得到许多、许多连接的可怕低效列表。它被认为是一种反模式是有原因的。并不是说您有时不应该使用它,只是需要仔细权衡成本/收益。
  • @A.H.您忘记添加“在某些情况下,EAV 示意图是问题域数据建模的最佳方法”,这完全取决于许多因素并最终针对您的用例进行测试。
  • @JustBob:这些情况很少,而且现在可以通过 NoSQL 数据库或使用非标准扩展作为 PostgreSQL 的 hstore 更好地解决。在任何实际案例中,我都看到 EAV 的实施不是因为领域需要它,而是因为一些中间框架(再次)发现了如何实现超灵活的“好”想法。因此,我对此有点尖锐。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多