最好有数百列或拆分成多个表?
Posted
技术标签:
【中文标题】最好有数百列或拆分成多个表?【英文标题】:Best to have hundreds of columns or split into multiple tables? 【发布时间】:2010-09-30 12:07:27 【问题描述】:我正在设计一个有关机械设备运行的统计数据库。每批数据将包含数百个统计信息,因此我试图决定是创建一个包含数百列的表还是将其拆分为多个表,每个表都包含相关的统计信息。例如,我可以有一个包含与故障相关的统计信息的表,另一个包含与堵塞相关的统计信息的表,等等。
使用多个表会使系统总体上更加复杂,尽管从概念上讲,处理几个较小的表比处理一个大的表可能更容易。
拆分是否有任何性能优势?似乎查询具有几十列的表可能比查询具有数百列的表要快。
有没有人有这方面的经验?我在这个项目中使用 Oracle,虽然这可能是我将来在没有数据库的情况下会遇到的问题,所以任何数据库的答案都将不胜感激。
【问题讨论】:
【参考方案1】:我认为我们需要更多地了解您的设计才能正确回答。例如,我很好奇可能有很多与故障有关的列,很多(不同的)与堵塞有关的列等等。(堵塞不只是一种故障吗?)
你的设计标准化了吗?大概你没有“jam1”、“jam2”等列?!
假设设计良好且规范化,是否拥有一张宽桌子或多张窄桌子的决定是各种因素之间的权衡:
是否所有/大多数记录都有所有类型的统计信息?是 => 一张桌子,没有 => 很多 您是否经常需要同时查询所有类型的统计信息?是 => 一张桌子,没有 => 很多 您是否在同一个屏幕中同时维护所有不同的统计数据?是 => 一张桌子,没有 => 很多 您是否可能达到任何数据库限制,例如?每个表最多 1000 列?无论采用哪种方式,您都可以使用视图来呈现替代结构,以方便开发人员:
一个表:许多视图选择特定类型的统计信息 许多表:将所有表连接在一起的视图更新
从您的 cmets 中,我现在知道您对机器上 40 个不同位置的卡纸进行了计数,而其他类型的统计数据也属于类似性质的计数。这建议采用以下表格设计:
create table machines (machine_id ... primary key, ...);
create table machine_stats
( machine_id references machines
, stat_group -- 'jams', 'malfunctions' etc.
, stat_name -- 'under the hood', 'behind the door' etc.
, stat_count
);
正如下面有人评论的那样,这些可以让您更轻松地汇总统计信息 - 在统计类型内或跨统计类型。如果需要将新的统计信息添加到统计类型,它也很容易扩展。
【讨论】:
每个卡纸统计数据是机器中特定位置发生卡纸的次数。因为有 40 多个不同的地方会发生堵塞,所以我们有 40 多个堵塞计数。我们的大多数统计数据都是这样的计数。 乍一看,这听起来像是可以归一化为卡纸位置,卡纸计数。如果给定行的 40 个卡纸计数中的大多数为 0,这将是值得考虑的。 即使大多数堵塞不会为零,我认为 smacl 的建议值得遵循。宽桌子让我头疼。另外,如果你想计算总堵塞怎么办? JamPos1 + JamPos2 ...变老快。 sum(jams) 更好。 感谢您的更新!我没有想过使用统计组字段来轻松高效地索引、检索和汇总相关统计信息,但这是个好主意,我可能会这样做。 我要告诉你一件事,在解决逻辑中的错误时,与一些较小的表相比,宽表使弄清楚到底发生了什么变得更加复杂。所以,我会尽可能地打破这种关系,因为它不仅有助于解决错误,还有助于设计系统。当你有一张大桌子时,有时在它周围工作也会变得复杂。对于大多数人来说,这可能准确,也可能不准确,但这是我从两家航空航天公司获得的经验。一个是用较小的表来做的,另一个是用很多列来做的。【参考方案2】:当我在一个表中看到数百列时,我倾向于怀疑数据架构没有被正确规范化。数百列真的是独一无二的,还是它们是可以归一化为更小的表的类似事物的组?
如果您可以减少列数,您就有可能减少所处理的数据总量,从而在多个级别上提高性能。例如,如果您有一条包含 1000 字节数据的记录,并且您想为每条记录更改 1 个字节,则可能会不必要地获取和存储 999 字节。这确实会影响性能。
【讨论】:
谢天谢地,看起来一旦输入了这些数据,它就永远不会被修改,尽管它最终会被删除以释放空间。【参考方案3】:规范化可确保您不会在架构中重复数据。
当然,你应该走多远是有限制的。 7 个或更多表的 JOINS 性能不佳。
但是一张怪物桌子?我会分手的。
【讨论】:
【参考方案4】:您是指 100 种类型的统计数据吗?
一些医学数据库尝试了一种称为“实体属性值”或“EAV”的模式或习语(您可以谷歌搜索这些术语):原因是关于患者的事实有无数不同类型,可能或可能没有为任何给定的患者捕获,并且 EAV 是一种更好的方式来存储它而不是在一个表中有无数不同的列。
但要注意 EAV 是有争议的:有人说这是“代码味道”和典型的新手错误;其他人说它偶尔(或很少)有用,但取决于(指定和拥有)对元数据的良好支持。
【讨论】:
我的意思是数百种统计数据。感谢您对 EAV 的建议;我会调查一下。 我意识到这是一个旧线程,但我在医学数据库工作,我永远无法决定是否应该拥有一个包含所有非重复数据点的非常宽的表,或者将其拆分为'逻辑'位。请记住,如果将其拆分,则需要一种方法将表重新连接在一起(如果需要)。一些数据库对在任何单个语句中可以加入多少个字段有非常严格的限制(我特别认为是 Access 女士)。就我个人而言,我永远无法决定哪种方式是最好的跳跃方式。【参考方案5】:我倾向于不喜欢列太多的表格。您可能会考虑的一种选择是将统计信息作为行存储在统计信息表中:
CREATE TABLE Statistics (id AS INTEGER PRIMARY KEY, statusType As VarChar,
statusValue As Float);
然后,您只需为要跟踪的每个状态添加一个新行。从数据库的角度来看,这要干净得多,但它确实使获取数据的报告变得更加棘手。
【讨论】:
【参考方案6】:在这种情况下,我会创建几个表。一个是机器表。一个是问题查找表。最后,两者之间的联结表还包含与状态相关的信息。维护会更容易,写疯狂的报告也会更容易。此外,添加新的状态类型也会更容易。
machine
id
name
description
status_flag
id
caption
machine_history
machine_id
status_flag_id
information
然后您可以执行以下操作: select count(distinct machine_id) from machine_history where status_flag_id = 23 and information
唯一的事情是 machine_history 表中的信息字段可能需要包含数字或字符。如果是这种情况,我会创建两个信息字段,以免影响性能。
另外我假设有一个编程组件可以让您创建一些方法来轻松处理这些数据。
【讨论】:
除此之外,您还可以创建status_flag 类别,按您的不同类型对它们进行分组,例如故障、堵塞等。以上是关于最好有数百列或拆分成多个表?的主要内容,如果未能解决你的问题,请参考以下文章
怎样将一个excel表格的多个sheet拆分成多个excel表