【.com快译】简介:本文向您介绍数据库设计中的九个常见错误,希望能帮助您避免这些误区,构建出真正适合您项目预期的数据库。作为数据库设计人员,当你负责一个数据库项目时,在最初的设计过程中和将数据库部署到生产环境之后,不可避免地会遇到不同的挑战。其中一些可能是由于数据库中的设计疏忽造成的。也就是说,您早期做出的一些决定可能会对数据库的最终性能产生深远影响。因此,为了避免这些陷阱的出现,让我们来讨论一下数据库设计中的九个常见错误。1.计划不周就像盖房子一样,你不可能要求建筑工人在一个小时内打好地基,所以你需要提前计划好房子的蓝图。同样,您对数据库的初始设计和规划越好,最终系统和服务的性能就越好。因此,一个具有前瞻性的数据库绝不是一些临时的想法拼凑出来的。糟糕的设计很可能导致数据库本身的结构问题,而一旦部署到生产中,我们将面临昂贵的更换和调整的困境。虽然我们无法预测未来数据库可能出现的每一个问题,但良好的前期规划确实可以降低推倒重来的风险。2.未能理解数据的意图无论是存储个人数据的小型数据库,还是处理复杂信息的大型企业级数据库,每一种类型的创建和使用往往都是为了满足明确的数据意图。因此,设计者只有真正理解了数据库的用途,才能根据这些目标设计出最优的匹配模式。可以看出,他们需要问的关键问题包括:数据的性质和类型、获取的方法、存储和检索的频率和数量,以及相应的各种应用。比如那些每天下班后需要人工录入信息的数据库,无论是在设计模型上还是在数据量上,都与工业级复杂的可以实时自动抓取和存储数据的数据库不同。因此,设计的关键是保证数据处理的效率、可用性和安全性(参见《PostgreSQLSecurity》,https://www.datasunrise.com/datasunrise-for-postgresql/)。一味追求大而全的数据库是不切实际的,不能满足数据的具体应用需求。3、标准化程度不够数据库设计不是一个严格定义的过程。遵循相同设计规则的两个开发人员通常不一定设计相同的数据布局。这主要取决于各种软件工程项目的创新和数据库在其中的作用。尽管如此,与设计相关的一些核心原则可以在确保数据库的最佳性能方面发挥关键作用。其中之一是:规范化。数据规范化具体指的是将数据表分解为多个组件的技术。您可以一直这样做,直到每个数据表只代表一个事物,并且每一列只代表那个事物的一个属性。实际上,SQL主要是基于读取和操作规范化数据集。您可以使用FROM子句从一个表中提取数据,然后使用JOIN将其添加到另一个表的内容中。您可以通过生成各种数据表来表示数据的类型。因此,SQL的附加功能对数据库的开发和性能都至关重要。索引通过与键值完全同步来提高其有效性。当必须使用LIKE、CHARINDEX、SUBSTRING等类似命令来解析某列的组合值时,SQL语句被分解以减少数据被查找的次数。因此,规范化数据库对于简化开发和保持高性能至关重要。我们可以根据不同的标准化程度,满足数据库相关记录的插入、更新、查询、删除等需求。业界广泛接受的最佳实践是:数据库至少要达到第三范式(NormalForm,3NF)的标准化水平。当然,第四(4NF)和第五(5NF)范式也很实用,也很容易理解。4.冗余记录冗余的表和字段是数据库设计者和管理员的噩梦。它们消耗有限的系统资源来保证系统的整体安全、同步和备份能力。特别是对于一些大型数据库,其冗余字段记录可能达到数百万条,这对于计算资源来说显然是一个相当大的开销。在增加数据库本身规模的同时,它们不仅降低了系统的运行效率,而且增加了数据损坏的潜在风险。在这里,我们并不是说数据记录的冗余是不必要的,而是说数据冗余应该在相关记录的基础上按照规则和政策来实现,当超过保留期限和适用条件时,数据库管理员应该及时删除或销毁。5、索引不佳无论是用户还是应用,都可能需要查询一个数据表的多个列值。但是,随着表中行数的增加,相应的查询时间也会稳步增加。因此,为了加快查询速度,减少表容量的影响,我们需要对数据表的列进行索引,以便在调用SELECT查询时,秒级实现表中对应的记录条目。但是,SELECT功能的加速通常会导致更多的INSERT、UPDATE和DELETE命令。这很大程度上是因为索引本身需要与数据库的内容不断同步,这意味着大量的数据库引擎开销。因此,具有讽刺意味的是:您尝试加快SELECT查询的速度实际上可能会降低整个数据库的速度。这是过度索引的典型案例。解决上述问题的方法是为所有列提供单一索引,可以用来查询表中的不同主键。您还可以按不同的列从最常用到最少使用降序排序。总之,建索引是个技术活,需要你花时间去总结和调整。6.所有域值的单一表一张包罗万象的域表(domaintable)并不是设计数据库的唯一方法。记住,关系型数据库的构建理念是:数据库中的每个对象只代表一件事,不应该出现不明确的数据集。通过导航主键、表名、列名和各种关系,应用程序可以快速破译数据集的含义。即便如此,很多人在设计数据库的时候,还是忍不住滑入了数据表越来越多,数据库越来越复杂混乱的深渊。过去,业界普遍的做法是将多张表压缩成一张表,以简化设计。但这往往会带来效率低下、操作困难等问题。而且,SQL代码会变得越来越长,可读性也越来越差。可以看出,单字段表看起来像是一个抽象的文本容器,但它确实不是设计数据库的最佳方式。然后,作为归一化的一部分,我们需要对数据进行分离和分解,让每一行只代表一个事物,同时让多个域表区分不同的事物。好处是:使数据查询更容易。使用外键约束更自然地验证单字段表设计无法实现的数据。因为在单字段表中,每个表所需的各种键可能变得难以维护。每当您想向一个对象添加多种类型的数据时,只需添加一列或多列即可。小域表适合存储在硬盘的单页上,而大域表很可能分布在多个磁盘上的多个扇区。显然,将表存储在单个页面上意味着我们可以通过单次磁盘读取快速提取数据。由于这些字段表可能具有相同的基础用法和结构,因此拥有多个字段表不会阻止您为所有行启用相同的编辑器。7.糟糕或不一致的命名约定数据库设计者和开发者往往过于专注于他们面前的技术。非技术方面,例如命名约定,通常被放在优先级列表的首位,甚至完全被忽略。而这很容易导致灾难性的后果。客观地说,虽然命名约定可以由设计者决定,但实际上它对数据库文档的重要性是不言而喻的(我们将在下面讨论糟糕的文档)。由于数据库在系统中是比较持久和稳定的,命名约定让那些没有参与建设项目的人(比如:后续的系统管理员,程序员,甚至是用户)不需要去阅读上千页的文档,您可以轻松快速地理解数据表和列的含义。当然,对于如何准确命名各种数据表及其详细信息,业界仍未达成共识。因此,最重要的是强调“一致性”。一旦决定以某种方式命名对象,就在整个数据库中实施该规则。对于数据表的名称,我们应该尽可能完整或简洁地描述所代表的对象,每一列的名称都可以代表该对象的属性。对于简单的数据库,这并不难实现;但是对于需要建立相互引用关系的复杂数据表来说,严格遵循命名规则是一件比较麻烦的事情。值得注意的是,此类规则不应对列名或表名的字符长度施加过大的限制,避免使用不易理解或记忆的首字母缩略词。例如:我们很难猜测列名CUST_DSCR的含义;而CUSTOMER_DESCRIPTION会更好的表达列名的意思。同时,要避免重复。如果表名是“Students”,那么我们只需要使用Name、Address、Grade作为列名,而不需要重复使用StudentName、StudentAddress、StudentGrade。当然,我们不应该擅自使用那些保留字。如果您将一列命名为“索引”,您可能会混淆系统并产生不必要的错误。所以我们可以使用像StudentIndex这样的描述性前缀。8.糟糕的文档正如我们上面提到的,数据库命名约定往往反映在相关文档中。这些看似微不足道的文档准备,往往会“毁掉”一些优秀的数据库设计。在系统运行过程中,糟糕的文档会极大地阻碍运维团队进行各种故障排除、架构改进、升级和连续性保证。数据库设计者应该假设,如果有一天他不再支持他的数据库,他准备的相关文件应该可以让其他人轻松接手后续的设计、开发或管理工作。因此,好的文档必须包含各种列、表、关系和约束的定义,显示每个元素的使用方式。如果您可以适当地包含和说明一些预期值示例,将会提供更多信息。一些设计人员可能会狭隘地使用晦涩难懂的文档作为保护自己工作的一种方式,这反映出其他人无法理解目标数据库的稀缺性。这种短视的做法,不仅容易被管理层识破,还会为几年后的系统改造和代码改进工作挖很多“坑”。9、测试不充分无论是软件开发还是数据库设计,都离不开严格的测试和检查。不幸的是,由于临近项目截止日期,测试阶段常常被无情地跳过。当然,这是玩火的一种方式。一些本应在测试阶段发现并解决的错误和不一致,往往为系统上线后埋下各种隐患。没有用户愿意使用它,也没有管理员愿意维护一个充满错误的数据库。因此,在上线前进行各种深入广泛的数据库测试,将大大减少部署到生产环境时可能出现的故障次数和损坏程度。业界普遍认为,一个好的测试不是要找到每一个bug,而是要帮助你找到并修复大部分潜在的问题。小结众所周知,数据库开发设计是任何数据密集型项目的核心,与各种业务应用息息相关。因此,本文列举的九种设计中的常见错误,将在项目推进和系统运行过程中对数据库后续性能造成严重影响,造成高昂的修复成本。因此,我们应该在设计之初就尽量避免这些陷阱,从而构建出真正符合项目预期的数据库。原标题:数据库设计中最常见的9个错误,作者:MokhtarEbrahim
