这是构建数据库架构的一种荒谬方法,还是我完全缺少了什么?


61

我已经对关系数据库做了很多工作,并且认为我对良好模式设计的基本概念非常了解。我最近的任务是接管一个由高薪顾问设计数据库的项目。请让我知道我的直觉是否是“ WTF ??!?” -是必要的,还是这个人真是个天才,以至于他超出了我的领域?

有问题的数据库是一个内部应用程序,用于输入员工的请求。仅查看其中的一小部分,您就可以获得有关用户的信息以及有关所提出的请求的信息。我会这样设计:

用户表:

UserID (primary Key, indexed, no dupes)
FirstName
LastName
Department

要求表

RequestID (primary Key, indexed, no dupes)
<...> various data fields containing request details
UserID -- foreign key associated with User table

简单吧?

顾问是这样设计的(带有示例数据):

用户表

UserID  FirstName   LastName
234     John        Doe
516     Jane        Doe
123     Foo         Bar

部门表

DepartmentID   Name
1              Sales
2              HR
3              IT

UserDepartmentTable

UserDepartmentID   UserID   Department
1                  234      2
2                  516      2
3                  123      1

请求表

RequestID   UserID   <...>
1           516      blah
2           516      blah
3           234      blah

整个数据库是这样构造的,每个数据都封装在自己的表中,数字ID将所有内容链接在一起。显然,该顾问已经阅读了有关OLAP的内容,并希望获得“整数查找的速度”

他还具有大量存储过程来交叉引用所有这些表。

这是中小型SQL DB的有效设计吗?

感谢您的评论/答案...


12
哦,男孩,如果这让您说WTF,那么您可能还没有看到包含200多个列的表和超过1000行长的存储过程。
工作

42
+1代表感到尴尬后不删除。感谢您离开此页面,以便其他人可以学习。
韦恩·考特斯

2
@Job-实际上,我还没有-按行业我不是DBA(现在很明显!大声笑),因此我的SQL WTF阈值相当低。虽然,我完全错过了顾问设计的要点,但是我还是WTF发挥了自己的才能。曾经有一天你会感到愚蠢吗?
吉姆(Jim)

9
@吉姆:恭喜,您已经将愚蠢的一天变成了开明的一天。
韦恩·科特斯

3
诅咒那些高薪顾问!
davidsleeps

Answers:


73

对我来说很有意义。它只是非常规范化的,它赋予了您以前没有的很多灵活性。归一化的数据是一个麻烦。


您的答案很合理,仔细查看我的问题和模式,也许仅仅是他正在使用的大量表使我感到困惑。我大大简化了我的问题的示例,但是我看到了这个概念的合理性-他将事情分解得比我要多得多。igh,我不是DBA,这是一件好事!:)
吉姆

按照十分钟的规则学习设计:“现在正确的事情可能不会在十分钟之内。” 确保您的设计可以应对变化。
Blrfl 2011年

1
这种模式实际上具有一个优点,即当雇员被插入时,其部门必须存在。
Simon Richter

@SimonRichter:这是不正确的。可以在不存在任何部门的情况下创建Employee,反之亦然。
Daniel Dinnyes'7

@SimonRichter这种设计的好处是,首先,部门是一个独立的实体,其次,部门与员工之间存在多对多的关系,而不是像OPs这样的例子:一对一”(不能说多对一,因为它所指的没有独立的部门实体被称为关系)。
Daniel Dinnyes'7

48

我认为不是必须要使用WTF还是该家伙正在做任何疯狂的天才设计-这是非常标准的数据库规范化。

使用部门表的原因是,如果不将部门放在单独的表中,则必须与“销售”,“销售”,“销售人员”,“航行”和“销售”部门中的用户打交道,除非您采取预防措施。而拥有额外的表是(我知道的)最好的方法。

是否应该有一个UserDepartment表是一个比较棘手的问题,这当然意味着没有一个决策是明智的。一方面,当您所有表的设计和逻辑都假设每个用户一个部门,然后进行更改时,这是一种痛苦,另一方面,多年来无缘无故地进行额外的联接是一种现实的可能性,也是一种痛苦。

我个人会同意您的观点,认为UserDepartment表可能过于矫kill过正。即使包含了该表,但随着时间的流逝,人们可能会编写假设每个部门只有一个用户的查询,因此您将面临两全其美的局面-在需要表之前无缘无故地进行额外的联接,并且一旦允许每个用户有多个部门,代码将无法正常工作。

编辑-是否应该支持多对多关系的关键驱动因素是业务规则是否明确。如果您不知道多个部门的用户将如何工作,则添加表没有太大意义,因为您的代码可能无法正确处理多个部门的用户。

想象一下,您确实为每个用户允许了多个部门,以防万一。然后,您根据部门实施了用于分配佣金的业务规则。然后允许多个部门。幸运的是,您还具有远见卓识,可以考虑到这种方式编写佣金代码。不幸的是,您添加了两个部门中每个用户的佣金。管理层希望您以每次销售的人员角色为基础。那么,提前摆桌子有什么好处呢?那么您拥有“以防万一”根本不需要的其他表呢?

稍后编辑- 此后续问题解决了顾问可能想要添加所有这些中间表的另一个原因,该问题的答案给出了为什么重构数据库通常比重构代码更难的一些原因,这往往会促使您向“放入您可能需要的所有表”方法。


我想您是说我的WTF是什么-这个家伙正在使用这些中间表的TONS,对我而言,这似乎太愚蠢了。现在,我已将其分解为一个小得多的示例,对于该问题,我觉得很愚蠢,因为它似乎还不错。
吉姆(Jim)

5
正如您从很多评论中看到的那样,人们对“每Y永远只有一个X”的评论持怀疑态度。该顾问正在从“为什么每个Y只能有一个X”的投诉中掩饰自己。其中一些可能会出现。但是他将不负责维护具有许多联接(不是很糟糕,但是更难)并且必须针对尚不存在的业务规则(有害)正确的代码-想象一下问题“用户为什么会得到全部每个部门的权限,他们应该获得每个权限的最低值”或类似的值。
psr

@psr我认为有一个错别字:“假设每个部门只有一个用户的查询”应该不是“假设一个用户仅在一个部门的查询”?
BiAiB

@BiAiB-你是正确的,这就是我的意思。
psr

14

如果要求每个用户有多个部门,则此设计很有意义。唯一的困扰是UserDepartmentTable拥有UserDepartmentID不需要的替代键(只需使用UserIdDepartmentId复合主键即可)。

如果用户仅属于一个部门,那么您的设计就很有意义(尽管部门查找表仍然是一件好事)。


18
...每个用户最多可以建立一个部门。
Blrfl 2011年

1
确实是@Blrfl。今天从来没有想过的是明天的首席执行官,因为它不做,因此具有动脉瘤。
亚当·克罗斯兰

2
决定什么方法值得这种治疗的一部分是理解问题领域。在某些应用中,重要的是要知道公司已将#3804号员工称为Ann Smith和Ann Jones(结婚后),这将使员工表中的姓名正常化是一件理智的事情。在Jim的情况下,可能有必要扩展断路器表以保留历史记录,这样,如果Ann从HR转到IT,则与她相关的旧请求这一事实可能反映出这实际上是HR的请求,而不是IT的请求。
Blrfl 2011年

8
YAGNI-可以重构数据库。
JeffO 2011年

2
@Oded,某些ORM映射器(例如Entity Framework)不适用于具有复合主键的表。
maple_shaft

5

您的问题中有些要求不清楚。正确答案取决于客户的需求-如果我是您,我会向客户询问以下内容:

0-用户和员工之间有什么区别?

1-假设员工=用户,如果员工更换部门怎么办?

2-一组员工可以提出1个要求吗?

3-员工可以属于多个部门吗?首席执行官呢

4-是否有一部分员工可以提出请求?

5-删除员工记录(如果有)时,请求会发生什么?

6-您可以删除请求吗?删除请求后会发生什么(确保您不按RI删除员工记录)

7-员工可以多次提出“相同”请求(定义“相同”)

8-如何在离开公司时处理雇员的请求(取消请求或删除请求?)

可能还有更多问题,但我的观点是,解决方案取决于确切的要求和项目范围。确定后,即可直接导出架构。因此,提出的两种解决方案可能都是正确的。


这些是+1的大问题,在设计这种类型的架构之前需要先弄清楚。我喜欢你的逻辑流程。

@ Surfer513:感谢您的好评。
NoChance 2011年

1

我想添加几个要点表格说明,以您的高薪顾问的方式明确讨论使用联接表的潜在优势。

  • 正确地建立索引(例如,如果UserDepartmentTable为两个外键建立索引),由于外键不是唯一的,这样的联接表只会有很小的性能损失。如果保证外键是唯一的,那么根据我所知的一点数据库理论,查找UserDepartmentTable.Department并不比查找User表中的任何其他列“难” 。
  • 联接表使您可以更灵活地设置有关用户与部门之间关联的其他信息(例如,创建时的时间戳记)。
  • 联接表使您可以相当轻松地“版本化”关联(例如,当用户更改部门时,触发一些索引布尔型标记(例如UserDepartmentTable.Activefalse)并创建一个活动的新关联)。也可以使用两表模型(仅用户和部门)进行部门关联版本控制,但是这样做比较困难,需要至少增加一列或进行数据库杂技操作,以避免重复主键。
  • 它使您可以非常轻松地分配一对多或多对一或多对多关联。

话虽这么说,但有几个原因导致您不做您的高薪顾问。

  • 以上所有好处均预示了未来可能的需求,使今天的事情变得过于复杂。它不符合YAGNI。后来写一个从两表模型迁移到联接表模型的迁移是很困难的。当业务需要出现时,您可以这样做。在此之前这样做可能会造成混淆。
  • 它使其他开发人员感到困惑。是的,我想说的是,对于一个身材高大的网络开发人员(正在审查顾问的决定)的期望是理解和识别联接表,但是它仍然比必要的复杂得多,并考虑到缺乏业务需求,它引起混乱。

漂亮的分析-但是,我不会说我有任何的身材在我的日常工作的一个开发,但我在这里只有一个,谁知道任何有关DB / C#/ VB /等等......所以想我的一部分默认情况下为time dev。这是一个相当小的项目,因此顾问的席位和参加人数非常多,让我说“ wtf”(但是感谢您,我现在在说“ oic ...”)
Jim

相当老的话题了,但是仍然很相关...重构可能非常困难,假设您将来需要多个部门而不是一个部门,但是在Users中只有一个部门ID作为FK。您可能最终会得到重复的公投(Users.DeptID和UsersDepartmentsTable)或完整的垃圾,例如,Users.DeptID或XML中的逗号分隔列表。正如YAGNI或KISS所建议的那样,无法轻易添加正确的解决方案,但会受到阻碍。
埃里克·哈特

0

没有所需信息的完整结构,我不能说它是否可怕。但是至少显示的部分不是“ WTF”设计的。它似乎只是数据结构的3范式(嗯,理论上我们也有4阶和5阶)

在图中所示的两个“自然”和“人造”键之间,可以在UserDepartmentTable上进行一些讨论。正如我所见,仅此而已

出于很多原因,规范化是优秀的DB开发人员/设计人员的准则,* de *规范化有时在开发过程中经常用于速赢

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.