我有许多表对它们的大部分列值使用查找/枚举引用。例如:
人员表 - PersonID | 比赛代码 | 头发颜色代码 | 发型代码 | TeethConditionCode
位置表 - LocationID | 尺码 | 外观颜色代码 | ConditionCode
诸如 Race、Size、Color、Condition 等之类的东西只是对代码查找表的外键引用。此代码表还有其他字段,但对我的问题并不重要。该数据库用于 SaaS 应用程序,这意味着每个客户都可以拥有自己的颜色、种族、条件等列表。有些代码是静态的,客户无法更改。
是有 1 个代码表还是 2 种代码表更好(DynamicCodeTable 用于客户定义的代码表,StaticCodeTable 用于更改的代码表)还是我应该为每种代码类型(RaceCodeTable、HairColorTable、Condition 等)都有一个表?
我最担心的是所有的sql连接。我正在使用的 Person 表有 20 多个这样的代码属性。加入 20 个不同的表 VS 加入同一个表 20 次时,性能是否存在差异?拥有多个表意味着每个表会更小,并且查找“应该”花费更少的时间。但是拥有一张桌子也可能很快。有什么建议么?
4 回答
在过去的 15 年中,在“一个真正的查找表”(简称 OTLT)的主题下,对该主题进行了详细讨论。这种方法的优势突显了数据库新手。缺点会随着时间的推移而出现。请参阅以下链接了解 OTLT 缺点:
- http://tonyandrews.blogspot.com/2004/10/otlt-and-eav-two-big-design-mistakes.html
- http://web.archive.org/web/20100130062850/http://www.dbazine.com/ofinterest/oi-articles/celko22
或搜索以OTLT
找到更多讨论。
如果您为它们创建了许多查找表和许多维护屏幕,您可以通过创建一个巨大的 UNION 来创建一个模拟 OTLT 的视图,该 UNION 包括每个代码、每个描述以及存储代码描述对的表的名称. 如果您知道自己在做什么,则可以使用半自动方法生成这样的联合。我想半自动方法将使您能够为数百个查找表构建一个维护屏幕,然后在该屏幕和将在正确表中插入新代码的表之间放置一些逻辑。
至于让用户引入新的代码类型,而不仅仅是新的代码值,这会打开一大堆蠕虫。请参阅上面讨论 EAV 的文章。这很诱人,因为它允许用户设计自己的底层数据结构。如果您忽略性能,这在一段时间内效果很好。您无需向用户或主题专家学习数据结构,即可获得一个完美通用的数据库。
当它遇到真正的悲痛时,是当您尝试将数据用作集成数据库时,而不仅仅是关于数据的杂乱无章的意见。在这一点上,当您的客户期望生成例行报告时,您就进入了一些严肃的数据考古领域。祝你好运。
(编辑将“数据挖掘”改为“数据考古”)
在不了解应用程序或要求的更多信息的情况下,我建议为每种代码类型设置一个表。IMO 数据库设计会更加清晰和自我记录,以便为您拥有的每种类型的代码提供外键。
在重新设计我们相当宽的表时,我错误地认为所有这些查找表都是一个好主意。如此多的灵活性等,但最终编码变得更加困难,无法四处导航,这简直是一件痛苦的事。
那我学到了什么?
- 对于静态值,只需使用枚举 - 它更快更方便。必须根据有多少其他表可能引用同一变量来做出此决定。
- 坚持使用更少的查找表,而不是创建尽可能多的查找表。JOIN 慢得多。
- 为了帮助自己导航,设计数据库视图。它会让你的生活轻松很多。
- 作为奖励,如果您不希望您的客户接触某些表(即您的静态表)或接触枚举列值,您可以使用 MySQL(例如)细粒度权限来禁用对某些表中某些列的更改. 很多人没有意识到这些权限可以变得多么灵活。
存在潜在的性能差异。
只有 2 行的表在缓存中为这两个小行占用了大量空间。
如果您在单个表中有很多查找值,您可以有效地将这些值更密集地打包到缓存中。