数据库设计中的 9 大常见错误( 二 )


对所有列只提供一个索引,并且该索引和查询表所用到的主键不同,这种方法可以解决这个问题 。我们也可能按最常用到最不常用对列进行排序 。索引始终是一个微妙的平衡,归根结底要用对 。
所有域值的一个表包罗万象的域表不是数据库设计的最佳方法 。请记住,关系数据库的构建思想:数据库中的每个对象只代表一个事物 。任何数据集所代表的事物都不应该含糊不清 。通过查看主键、表名、列名和关系,我们应该可以快速解读数据集的意义 。尽管如此,对于数据库设计,一种挥之不去的误解是,表越多,数据库就越混乱越复杂 。
通常,把几张表压缩到一张表中就是简化设计的原理 。这听上去是个好主意,但是,通常得到的是效率低下且难以操作的数据库 。SQL 代码将变得很长,难以阅读,也不自然 。这将把两种截然不同的东西混在一起 。乍一看,域表看起来像一个抽象的文本容器 。从实现的角度来看,这是正确的,但是,这不是设计数据库的最好方法 。
作为规范化过程的一部分,隔离和分解数据最终形成每一行只代表一个事物 。每个域表与所有其他域表都不同 。
多个域表的最终结果是:

  • 使用在查询中的数据变得更容易 。
  • 可以更自然地用外键约束来验证数据,这对单域表设计来说是不切实际的 。我们可以用单域表来做,但是每张表所需的键将使维护变成雷区 。
  • 无论何时我们需要添加与某个对象相关的更多数据,该任务就像添加一个或多个列那样简单 。
  • 小型域表可以放入硬盘的单个页中,而不像大型域表需要分散在多个硬盘分区中 。表存放在单个页中意味着可以用单次硬盘读来完成数据提取 。
  • 拥有多个域表并不妨碍我们对所有行使用一个编辑器 。域表最有可能拥有相同的底层用法 / 结构 。
糟糕的或不一致的命名约定数据库设计人员和开发人员常常把他们的角色完全看作是技术角色 。非技术方面(如遵守命名约定)往往被推到优先级列表的较低位置,或者甚至完全被忽略 。这可能是个灾难性的错误 。
命名也许是设计人员自行决定的,但是,事实上,它是数据库文档的第一个也是最重要的元素(我们接下来将探讨文档错误) 。数据库设计人员应该把他们的工作看作是在他们换了雇主或角色之后还将继续存在的东西 。命名约定的目的是,让没有完全参与该项目的人也能比较容易地快速理解表和列的内容 。未来的管理员、开发人员或用户不应当必须看完长长的文档才能理解某个表名或列名的意义 。表如何命名的具体细节并未得到业界的一致同意 。
最重要的是一致性 。一旦我们遵循某个特定的风格来命名对象,那么在整个数据库中要坚持使用它 。表名必须尽可能是表所代表的内容的完整或简约描述,而列名应该清楚地表明其所代表的信息 。对于简单数据库,这并不难 。但是,一旦我们构建彼此引用的表,事情就变得复杂了 。严格遵循命名约定始终是正确的方向 。
这样的约定包括没有列或表名的字符长度限制,以消除使用不易理解或记忆的首字母缩略词的需要 。如列名 CUST_DSCR,任何人读到这个名字都将不得不猜测该列包含的内容 。CUSTOMER_DESCRIPTION 则是个更好的列名,没有迫使读者展开他们的想象力 。
避免冗余:在一张名为“Students(学生)”的表中,我们不必把列命标成 StudentName、StudentAddress 或 StudentGrade,因为 Name、Address 和 Grade 已经足够了 。还有,不要使用保留字 。用“Index”来标记某列会让人困惑,也会成为错误的来源 。可以用一个描述性的前缀,如 StudentIndex 。
糟糕的文档如果数据库开发人员和设计人员在确定命名约定的优先级上碰到问题,那么他们在文档方面就会存在更大的问题 。对于开发人员来说,文档有时感觉像是开发过程中一个微不足道的非必要方面 。然而,很多在其他方面设计优秀的数据库已经牺牲在糟糕文档的祭坛上 。糟糕的文档极大地抑制了故障排除、结构改进、升级和连续性 。
数据库设计人员必须始终想象他们会在某个时刻不再参与对该数据库的支持 。文档应该让其他人容易接手数据库设计、开发或管理 。良好的文档必须包含列、表、关系和约束的定义,使之清楚地表明每个元素应该如何使用 。如果我们可以包含示例以说明预期值,那么效果会更好 。
有些设计人员会使用糟糕的文档作为确保工作安全性的一种手段,即除了他们之外,没有人能完全理解该数据库 。这是一种短视和注定失败的策略,因为这几乎总是导致管理层看透设计人员的意图 。糟糕的文档还让我们作为设计人员多年后返工或改进这些代码变得非常困难 。


推荐阅读