在数据库领域,"为了正确性而进行规范化,为了性能而进行去规范化" 这个口号是否正确?
在数据库领域中,"为了正确性而进行规范化,为了性能而进行去规范化"是一个正确的口号吗?这个问题的出现是因为团队动态在系统开发中的重要性以及不同角色/人员的行为(或不当行为)的不同。规范化对于数据完整性非常重要,因为它不仅是一个关于设计模式的冷静的辩论,还与系统的设计和长期管理有很大关系。
数据库专业人员接受的培训强调数据完整性是一个重要问题。我们喜欢从数据完全正确的角度来思考,这样一旦数据进入数据库,就不必再考虑或处理逻辑错误。这种思维方式对规范化的重视很高,因为它迫使团队理解数据和系统的基本逻辑。以一个简单的例子来考虑:一个客户只有一个姓名和地址,还是可以有多个?有人需要做出决定,并且系统将依赖于一致应用该规则。这听起来像是一个简单的问题,但当你设计一个相当复杂的系统时,将该问题扩大500倍,你就会看到问题所在。规则不能只存在于纸上,还必须被积极执行。规范化良好的数据库设计(辅以唯一性约束、外键、检查值、逻辑强制触发器等)可以帮助您拥有一个定义良好的核心数据模型和数据正确性规则,如果您希望在许多人在系统的不同部分(不同的应用程序、报告等)上工作以及不同的人随时间在系统上工作时,这是非常重要的。或者换句话说,如果您没有某种方式来定义和操作性地执行一个坚实的核心数据模型,您的系统将是糟糕的。
其他人(通常是经验较少的开发人员)并不这样看。他们将数据库视为最多是与他们正在开发的应用程序有关的工具,或者最坏的情况下是要避免的官僚主义。这些经验较少的人常常会推动去规范化,以便快速而肮脏地设计和管理数据模型。这就是为什么您会得到数据库表与应用程序界面和报表一对一对应的情况,每个表反映了不同开发人员的设计假设,表之间完全缺乏理智和连贯性。我在职业生涯中已经多次遇到过这种情况。这是一种令人沮丧和极其低效的系统开发方式。
因此,人们对规范化有强烈的感觉,这是因为该问题是他们对其他问题的代表。如果您卷入了规范化的辩论中,请考虑各方可能带入辩论的基本(非技术)动机。
话虽如此,下面是对原始问题的更直接的回答:
有必要将您的数据库视为由核心设计和扩展设计组成的。核心设计尽可能接近逻辑设计-高度规范化和约束-而扩展设计则解决其他问题,如稳定的应用接口和性能。
您应该希望约束和规范化您的核心数据模型,因为不这样做将损害数据的基本完整性以及系统构建所依赖的所有规则/假设。如果您让这些问题脱离控制,您的系统可能会很快变得糟糕。根据需求和真实世界数据测试您的核心数据模型,并不断迭代,直到它正常工作。这一步骤更像是澄清需求而不是构建解决方案,而且应该是这样的。使用核心数据模型作为强制功能,以获取有关这些设计问题的明确答案。
在转向扩展数据模型之前完成核心数据模型。使用它并看看您能达到什么程度。根据数据量、用户数量和使用模式,您可能永远不需要扩展数据模型。尝试使用索引和DBMS中可以调整的其他性能相关参数。
如果您真正达到了DBMS的性能管理能力的极限,那么您需要考虑在保留规范化的同时扩展数据模型以添加去规范化。请注意,这不是指规范化核心数据模型,而是添加处理去规范化数据的新资源。例如,如果有一些巨大的查询影响了性能,您可能希望添加一些预计算这些查询将产生的数据的表-本质上是预执行查询。重要的是以一种保持去规范化数据与核心(规范化)数据的一致性的方式进行此操作。例如,在支持的DBMS中,您可以使用MATERIALIZED VIEW使去规范化数据的维护自动化。如果您的DBMS没有此选项,那么您可以通过在包含基础数据的表上创建触发器来实现。
在以一种考虑周全和连贯的方式选择性地去规范化数据库以应对现实性能挑战的设计之间存在着巨大的差异,而不仅仅是一个弱数据设计,并将性能作为其正当理由。
当我与经验较低至中等的数据库人员和开发人员合作时,我坚持要求他们制定一个绝对规范化的设计...然后可能会邀请少数经验较丰富的人员参与到有关选择性去规范化的讨论中。去规范化在核心数据模型中几乎总是不好的。在核心之外,如果您以经过深思熟虑和连贯的方式进行去规范化,那么没有任何问题。
换句话说,从一个规范化的设计选择性地进行去规范化,以保持核心的规范化,并添加一些去规范化的物理数据,以处理数据的现实情况,是可以的。那些没有核心规范化设计的设计,本来就不应该被称为去规范化,因为它们从未经过有意识的、纪律性的设计。这不是好的。
不要接受弱、不规范的设计被称为"去规范化"设计的术语。我相信关于有意识/谨慎地去规范化数据与仅仅因为设计师粗心而导致去规范数据的普通糟糕数据库设计之间的混淆是关于去规范化的许多辩论的根源。
最后一段话值得记住。一些去规范化的设计是有纪律和功能性的。其他的则只是懒散和随意。
关于NoSQL数据库,您对它有何看法?只有在传统关系数据库性能不足的情况下才会使用它们吗?
这是一个经典的权衡。对于某些应用程序来说,NoSQL非常好,但它会给应用层增加更多管理数据完整性的负担。这是一个非常简化的说法,但当数据不是极其重要时,NoSQL是一个很好的选择。我喜欢核心数据使用关系型数据库,而使用其他数据存储来支持关系型数据库,例如REDIS用于热数据(但:往返到关系型数据库),其他NoSQL用于瞬态数据等。这是一种不同类型的去规范化,并且需要有意识地进行。您应该有明确的原因,为什么特定的数据集存在于每个层中。
在数据库领域,"Normalize for correctness, denormalize for performance"(为了正确性进行规范化,为了性能进行去规范化)这个口号是否正确的问题的出现是因为人们对规范化和去规范化的理解和应用存在一定的困惑。在解决这个问题时,可以采取以下方法。
首先,需要明确规范化和去规范化的概念和作用。规范化是指通过分解数据库中的关系模式,消除数据的冗余和更新异常,从而提高数据的一致性和完整性。而去规范化则是为了提高查询性能,而有意地引入冗余数据,减少表之间的关联。
接下来,通过分析的问题内容,可以得出以下结论。在性能方面,如果需要提高查询性能,可以考虑去规范化。而在错误消除方面,规范化是更好的选择。因此,原始的口号"Normalize for correctness, denormalize for performance"是合理的,但也可以加上一个条件,即只有在必要时才进行去规范化。
同时,需要注意的是,规范化并不直接涉及数据的正确性,而是通过更好地组织数据来减少冗余。而数据正确性是数据本身的质量,而不是组织方式。因此,规范化和数据正确性是两个不同的概念。
对于2020年是否仍然适用这个口号的问题,可以得出结论是适用的。但对于NoSQL数据库来说,它的横向扩展性更强,将数据分散到多个表中会使一切变得更慢和更复杂。因此,更推荐采用文档或聚合模型。关于如何在NoSQL数据库中存储具有多对多关系的领域对象,可以参考Vaughn Vernon关于聚合设计的文章,这是一个很好的起点。
文章的输出如下:
在数据库领域,"Normalize for correctness, denormalize for performance"(为了正确性进行规范化,为了性能进行去规范化)这个口号是否正确的问题的出现是因为人们对规范化和去规范化的理解和应用存在一定的困惑。在解决这个问题时,可以采取以下方法。
首先,需要明确规范化和去规范化的概念和作用。规范化是指通过分解数据库中的关系模式,消除数据的冗余和更新异常,从而提高数据的一致性和完整性。而去规范化则是为了提高查询性能,而有意地引入冗余数据,减少表之间的关联。
接下来,通过分析的问题内容,可以得出以下结论。在性能方面,如果需要提高查询性能,可以考虑去规范化。而在错误消除方面,规范化是更好的选择。因此,原始的口号"Normalize for correctness, denormalize for performance"是合理的,但也可以加上一个条件,即只有在必要时才进行去规范化。
同时,需要注意的是,规范化并不直接涉及数据的正确性,而是通过更好地组织数据来减少冗余。而数据正确性是数据本身的质量,而不是组织方式。因此,规范化和数据正确性是两个不同的概念。
对于2020年是否仍然适用这个口号的问题,可以得出结论是适用的。但对于NoSQL数据库来说,它的横向扩展性更强,将数据分散到多个表中会使一切变得更慢和更复杂。因此,更推荐采用文档或聚合模型。关于如何在NoSQL数据库中存储具有多对多关系的领域对象,可以参考Vaughn Vernon关于聚合设计的文章,这是一个很好的起点。
在数据库中,对于正确性而言,"规范化以保证正确性,去规范化以提高性能"是否是一个正确的口号?这个问题的出现主要是因为去规范化会提高检索效率,但在修改操作(插入、更新,有时甚至是删除)时会增加数据验证的复杂性。通常情况下,这种额外的复杂性被忽视了,导致数据库中存在虚假数据,这往往直到后来才被发现-比如在有人试图弄清楚公司为何破产时发现数据是自相矛盾的,因为数据被去规范化了。
我认为这个口号应该是"规范化以保证正确性,只有在高级管理层提出将你的工作交给其他人时才去规范化"。此时你应该接受这个机会去找新的发展,因为当前的工作可能无法像你希望的那样持久存在。
或者"只有在管理层给你发送一封免责的邮件后才去规范化,以证明你对即将发生的混乱不负责"。
当然,这假设你对自己的能力和对公司的价值充满信心。
对于指出政治因素的+1;现代数据库采用缓存策略,通常情况下规范化的数据在大多数查询中的性能表现优于非规范化的数据。首先进行性能分析,然后再决定是否去规范化。
Steven:有针对规范化数据库效果更好的缓存策略吗?我想了解一下这些策略...