如何更好地为应用程序设置数据库?规范化 vs 现实世界

3
请考虑下面这个数据库支持的应用程序设置(在我的情况下,DB是MySQL,应用程序是Ruby(Rails 3),但我认为对于这个问题来说并不重要)。
假设我有一个仓库应用程序。
我有多个项目,其中会有类别和状态。
例如,具有零件的表格将有一些状态,例如:现货、停产、缺货以及多个类别,例如:IT硬件、汽车、医疗等。
此外,我还有其他需要状态和类别的表格,例如 供应商:已批准、已倒闭、新 订单:开放、处理中、已发货、已取消。
等等。
问题在于:
我认为如果我想正确地规范化我的数据库-我会有一个称为categories、categories_types、statuses、statuses_types的表格。
然后我会将所有类别存储在那个表格中,并且任何属于某种类型的类别,例如所有零件类别,都会有一个外键指向category_type - parts,以此类推。类型也是如此。
这是标准化的方法。
然而,我经常看到人们为特定类别创建单独的表格,例如, 会有一个名为part_categories、vendor_categories、order_statuses、part_status的表格。这是一个不太标准化的数据库,但我想当你处理很多表格时,它可能更清晰。
这两种方法哪种更好?在你的经验中有什么优缺点? 我通常选择第一种设置,但我经常看到第二种设置,所以我开始怀疑我的方法。
谢谢。
2个回答

4
我认为这取决于您与数据的交互方式。第二种方法的好处在于可以轻松查看与特定对象(供应商、项目、订单)相关联的类别和状态。请记住,如果您使用第一种方法,则可能需要在类别和状态表中具有类型标识符,以标识行所关联的类别或状态的种类(供应商、项目、订单)。
第一种方法的好处是更容易为新对象添加状态和类别,并且只有两个表格的简单性。问题出现在您想要向特定类别或状态添加其他信息时。例如,如果订单状态需要具有生效日期,但项目状态不应该具有生效日期。一旦到达此点,您将不得不转向第二种方法或添加一个对于其他状态不适用的属性而为空的生效日期。
请记住,另一种方法是根本不创建状态和类别表,而是将状态和类别值存储在原始表中。您可以在MySQL或Rails中使用可枚举(ENUM)来完成此操作。在MySQL中,ENUM作为整数存储在数据库中,但它解析为单词值,如“processed”、“shipped”或“canceled”。这样做的好处是,如果您的状态不经常更改,则可以少进行一次连接,并且更容易读取数据库和Ruby模型。在Ruby中,ENUM可以简单地是一个具有键(整数)和与其关联的值(字符串)的常量列表。您可以使用整数值来查询和更新数据库,并在应用程序端使用单词值。
我认为这两种方法都是合法的,您采取的路径确实取决于您的需求。如果您决定将数据存储在数据库中,请分析与状态和类别交互的方式-您的方法可能不同。哪种方法将更快,更易于查询?哪一个更容易更新或修改?您有多频繁读取;您有多频繁写入?最后,请记住,您是敏捷的!任何一种方法都可以通过简单的迁移和一些重构转换为另一种方法。现在对您的应用程序最简单的方法可能不是将来使用的最佳方法,这完全可以接受。这就是敏捷的伟大之处!

谢谢你 Pan,非常清晰易懂的回答。关于你的第一个观点 - 我有两个表 - category_types 和 status_types,它们保存状态和类别的指示器。ENUM 方法对我来说行不通 - 因为状态总是在变化:open,processed,active,discontinued等等。请记住这是一个巨大的仓库。另外,关于你提到的额外属性,比如有效数据,我不能使用表继承吗:例如创建一个模型 OrderStatus < Status? - konung
是的,你可以这样做,这绝对是一个可行的选择。这意味着你需要加入另一个表,这可能会导致速度变慢和复杂度增加。如果状态经常变化,使用ENUM类型也是可以的。但是,当可分配给订单的可用状态的范围经常发生变化时,ENUM类型就不适用了。 - Pan Thomakos

2
根据我的经验,列举名称的表通常最终会演变成它们自己的完整模型。通常情况下,它始于添加布尔标志,或者如上面的答案中提到的引用类型或有效日期范围。
从关系的角度来看,将所有状态枚举放在一个表中或将它们分成单独的表,两种方法都不比另一种“更”规范化。但从类型理论的角度来看,将part_categories和vendor_categories放在它们自己的单独表中更有意义,因为这样做不需要在模型中编写任何代码,以确保您不会意外地将供应商类别与零件相关联。
如果您最终将它们全部放在同一个表中,Rails有一个很好的功能,称为多态关联,可以为您自动处理类型和ID列。这是两种方法之间的一个合理折衷。
最重要的是,我认为这些枚举最终将拥有自己的模型生命周期,在这种情况下,您需要费力地在各个表中找到它们,并将它们重新转换为自己的表。表格很便宜,为什么要节约呢?

谢谢Jim。我大多数时候都在使用多态表,只是想弄清楚为什么人们会创建多个类别表,如果有我没看到的原因的话。对我来说,它们总是看起来像需要在一个表中查看的相同内容。正如你所说,表格很便宜,但当你的数据库有超过400个表时,就开始有点混乱了 :-) - konung

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接