带有额外列的单个表与具有重复模式的多个表


13

我正在一个项目上,在某个时候,我需要决定是否要在数据库中的单个表中包含不是每个记录都使用的多列,或者是多个表具有重复的模式。

我正在创建一个体育信息应用程序,它可以处理多种体育运动。例如,我们可以处理NBA,NHL,MLB,NFL。每种运动都有非常相似的概念-球队,日程表,伤害,球员信息。

当然,我们的数据源并不能为我们提供同一模式中的每条数据。每个运动都有一个不同的架构,我们从供应商那里接收数据。

因为没有足够的时间(客户需求)对数据源进行前期分析以确定共同点,所以我对冲了自己的赌注并进行了“安全下注”,为每种运动制作了单独的表格,而不是一组单独的表格体育使用。

结果是在多个表中复制了架构,因此也复制了数据库的接口(例如存储的proc)。我有一些类似NBA_Game,NFL_Game,NBA_Team,NFL_Team等的东西。每个表可能有一些其他人没有的属性,并且有几个是共享的。在4项或5项运动中,连续进行5-10桌。我仍然不确定这是否完全是一件坏事-另一种选择是,拥有一组表,表上具有并非所有运动项目都会使用的属性,它本身也可能很笨拙。

有谁做过这种设计的陷阱,可以在这里分享他们的经验吗?也许可以帮助我现在知道的事情,而不是刻苦学习的东西?您是否以另一种方式完成了工作,即拥有一个大表/一组表,并且使用了并非每条记录都会使用的列?您遇到了什么陷阱?

过去是否使用过一些替代方法,例如表继承,效果更好?

谢谢

Answers:


12

最终,它归结为使用和体系结构。

建筑

系统是否处理“任何运动”?您是不是戴上了宇航员的建筑帽,并构建了一个通用系统来处理将来甚至可能不存在的未来运动的想法?

如果是这样,显然拥有动态命名的表将是一个巨大的痛苦,因此,如果需要,具有支持n体育的模式将是有意义的。

就是说,我对这种方法有很大的偏见:这几乎总是更多的工作,并且导致较差的结果。为每种运动创建单独的UI,架构等最终将带来更好的用户体验,并且更易于维护代码,即使这确实意味着一定程度的表面重复(如何避免/最小化这是一个单独的问题)。

您如何处理进行多项运动的球员?他们得到两个条目(例如,您对待不同的人)还是要尝试对他们做一些特定的事情?

采用

因此,假设您没有动态进行运动(例如,如果某人想要添加一项新运动,则需要开发人员才能添加它)。

有没有一次您一次显示一项以上运动中的球员(或您提到的任何其他物体)?

我可以在搜索功能中看到它,您可以在其中按球员或球队名称(无论运动项目)进行搜索,但是除此之外,我无法想象很多用例。

如果您永远不需要这样做,那么您的方法就很好。您可以在这里停止阅读。

替代方案

观看次数

我是KISS的粉丝。在15多年的软件开发中,我继续回到“构建最简单的工具”这一理念。

因此,假设跨运动搜索功能确实是唯一的用例,我的最初反应是创建视图:

SELECT PlayerName, 'NFL' as [Sport], TeamName FROM NFL_Players JOIN NFL_Teams ... 
UNION  
SELECT PlayerName, 'NHL' as [Sport], TeamName FROM NHL_Players JOIN NHL_Teams ... 
UNION ....

当然,如果添加新运动,则必须添加到视图中。包括其他公共信息也可能很有用,但实际上这取决于需要显示的内容。

我会尝试将所有特定于运动的内容保留在View定义中,因此搜索代码不需要有太多或任何特定的代码(可能知道如何链接到/nhl/players/player-namevs,/nfl/...或者您的应用可以执行此操作)。

表继承

表继承可以工作,但是非常复杂。我没有很多经验,实际上,我认为每次参与评估时,我们都会做一些简单的事情(就像我在这里建议的那样)。

因此,就我个人而言,我还没有找到为什么这样做会有用,但是也许有一个令人信服的用例(我不知道)证明了复杂性(例如,表继承比其他解决方案更好地解决了用例) 。

特定运动属性的单独表格

您可以创建一个players表,该表具有所有运动的所有玩家共有的属性,然后创建另一组表nhl_players_details,其中包含一个playerId和带有该玩家其他信息的列。如果有很多共同的属性,或者您对“所有运动的所有参与者”都有很多用法,那么这可能是有道理的。

运动特定属性的键值对

完全替代的方法:有一个players表(再次,与像名共同属性),然后player_data有表PlayerIdSportAttributeValue。输入的属性名称将特定于运动。这样一来,您基本上可以在不修改架构的情况下添加新属性(当然,您的代码仍然必须知道如何加载/显示它们)。缺点是您失去一些完整性:值通常是一个字符串字段,因此您的应用程序代码将必须具有弹性,并处理将字符串value转换为特定数据类型(如整数)的潜在失败。

这个概念当然可以应用于团队,游戏等。


寻找一个遗留项目的解决方案将有多个可验证的类型和表格,这里我已经忘记了这里提到的视图,这确实为我的研究提供了另一种可能的解决方案。谢谢。
FullStackFool

5

您正在谈论数据库规范化。您可能会发现,没有完美的数据模型之类的东西会让您放心,而且更多的规范化并不总会更好。规范化可能会增加数据模型和数据库性能的清晰度。因此,最佳选择模型将取决于您的使用要求。

从表面上看,您的示例在概念上似乎足够相似(X_Game与Y_Game和X_Team与Y_Team),以至于几列的额外开销似乎并不合理。就是说,如果每个运动都将在表中增加几十个额外的列,那的确是不方便的。

在这种情况下,您可能希望考虑使用混合模型,在该模型中,公共数据保存在中央表中,而运动特定数据保存在链接数据结构中。就像是:

table Game {
    gameId int,
    teamId1 int fk,
    teamId2 int fk
}

table HockeyGame {
    gameId int fk,
    penaltyMinutes int
}

table BasketballGame {
    gameId int fk,
    freeThrows int
}

这就是我要提出的内容,或者可能是“游戏”表中的一列指示游戏类型。我意识到可以通过加入其他表来推断出来,但是如果游戏类型的数量增加,那将变得乏味。
罗里·亨特

绝对-这只是一个骨架模型,用于说明核心关系以及一些示例,这些示例可能是常见数据还是运动特定数据。
Midnotion
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.