性能提升与规范化表? [关闭]

Posted

技术标签:

【中文标题】性能提升与规范化表? [关闭]【英文标题】:Performance gains vs Normalizing your tables? [closed] 【发布时间】:2014-08-28 18:48:44 【问题描述】:

好吧好吧,我知道你们可能会因为问这个问题而杀了我,但是我与一位同事就我们的一个数据库表进行了友好的程序员争论,他问了一个我知道答案的问题,但我无法解释这是更好的方法。

为了问题的简单性,我将简化情况,我们有一个相当大的人员/用户表。现在在存储的其他数据中,有问题的数据如下:我们有一个 simNumber、cellNumber 和该 sim 的 ipAddress。

现在我说我们应该创建一个表,我们将其命名为 SimTable 并将这 3 个条目放入 sim 表中,然后将 FK 放入连接两者的 UsersTable 中。为什么?因为这就是我一直被教导的 标准化你的桌子!!!好的,在这方面一切都很好。

但是现在我的朋友对我说是的,但是现在当你想查询用户的电话号码时,现在必须执行 SQL 并且:

    搜索用户 搜索 sim fk 在 sim 数据库中搜索正确的 sim 行 获取电话号码

现在,当我去请求 10000 个用户电话号码时,完成的操作数量会大大增加。

与其他方法相比

    搜索用户 找到电话号码

现在这个论点纯粹是基于性能的。据我所知,我们为什么要对数据进行规范化(以删除冗余数据、可维护性、对一张表中的数据进行更改以向上传播等。)在我看来,在一张表中使用数据的方法会更快或者至少会减少任务/操作来给我想要的数据?

那么在这种情况下是什么情况呢?我真的希望我没有问任何疯狂愚蠢的事情,现在是清晨,如果我没有想清楚,请原谅我

MS SQL server 2012涉及的技术

[编辑] 下面这篇文章还涉及到我上面提到的一些概念 http://databases.about.com/od/specificproducts/a/Should-I-Normalize-My-Database.htm

【问题讨论】:

如果您假装每个人实际上都拥有相同的电话号码并且甚至不费心存储它,您可以获得更好的性能。快速和错误很容易。 如果你规范化的唯一原因是你被教导总是规范化,那么难怪你不知如何说服同事,尤其是程序员。每种归一化形式(1NF、2NF、3NF、BCNF、4NF、5NF...)一旦被发现就受到青睐,这是有原因的。最终标准化和其他一些设计之间也存在权衡。一旦您了解了权衡取舍,您就可以更好地为您的设计提出理由。 【参考方案1】:

标准化的目标不是性能。目标是以最小冗余正确建模数据,从而避免数据异常。

例如,两个用户共用同一部手机。如果您将电话存储在用户表中,您将在每个用户的行中存储一个 SIM 卡号码、IP 地址和手机号码。

然后您更改某一行的 IP 地址,但不更改另一行。一个SIM卡号怎么可能有两个IP地址?这甚至有效吗?哪一个是正确的?您将如何解决此类差异?您如何检测到它们?

有时,如果您确实需要为您非常频繁运行的一个查询优化数据访问,那么反规范化是值得的。但是非规范化是有代价的,因此请准备好投入更多的手动工作来承担数据完整性的责任。更多代码,更多测试,更多清理任务。在考虑整个项目的“性能”时,这些是否重要?


回复:

我同意@JoelBrown 的观点,一旦您实施了第一个非规范化案例,就会损害数据完整性。

我将扩展 Joel 所说的“经过深思熟虑”。非规范化有利于特定查询。因此,您需要知道您的应用中有哪些查询,以及您需要优化哪些查询。保守地这样做,因为虽然非规范化可以帮助特定查询,但它损害相同数据的所有其他用途的性能。所以你需要知道是否需要以不同的方式查询数据。

示例:假设您正在为 *** 设计一个数据库,并且您希望支持问题标签。每个问题可以有多个标签,每个标签可以应用于多个问题。规范化的设计方法是创建第三个表格,将问题与标签配对。这就是多对多关系的物理数据模型:

Questions ----<- QuestionsTagged ->---- Tags

但您认为您不想通过连接来获取给定问题的标签,因此您将标签放入问题表中以逗号分隔的字符串中。这使得查询给定问题及其相关标签的速度更快。

但是,如果您还想查询一个特定标签并找到其相关问题怎么办?如果您使用规范化设计,它只是针对多对多表的查询,但在 tag 列上。

但是,如果您通过将标签作为逗号分隔列表存储在问题表中来进行非规范化,则您必须在该逗号分隔列表中搜索标签作为子字符串。搜索子字符串无法使用标准的 B 树样式索引进行索引,因此搜索相关问题成为代价高昂的表扫描。插入和删除标签或应用唯一性或外键等约束也更加复杂和低效。

这就是我所说的非规范化改进一种查询的意思以牺牲数据的其他用途为代价。这就是为什么最好从正常形式的所有内容开始,然后在瓶颈暴露出来时根据具体情况重构为非规范化设计。

这又回到了古老的智慧:

“过早的优化是万恶之源”——Donald Knuth

换句话说,在您能够在负载测试期间证明 (a) 它确实对性能进行了改进以证明数据完整性的损失是合理的,并且 (b) 它不会使其他情况的性能下降到无法接受的程度之前,请不要进行反规范化.

【讨论】:

所以基本上,你所说的总结是,非规范化更快更好地提高性能,但你失去了数据完整性。所以目标是在不丢失数据完整性的情况下尽可能地去规范化。 @Zapnologica - 你不能在不冒丢失数据完整性的风险的情况下进行非规范化。这就是标准形式的定义方式。目标是规范化您的表,然后在非规范化方面做出深思熟虑的选择,如果这成为处理您在现实世界负载测试中发现的实际性能问题的最佳方式。第一个目标应该是保持数据正确。如果数据错误,快速是没有意义的。也不要假设 RDBMS 对标准化数据不会很快。这就是他们天生要做的事情。【参考方案2】:

听起来您已经了解标准化的好处,所以我不会介绍这些。

这里有几个注意事项: 1. 用户是否始终只有一个电话号码? 如果是这样,那么将这些添加到用户表中仍然是标准化的。但是,如果用户可以没有电话号码或有多个电话号码,则电话详细信息应保存在单独的表中。

    假设您将这些放在单独的表中,但在执行性能测试后发现加入这两个表对性能有显着影响,那么您可以选择故意对表进行非规范化以提高性能。

【讨论】:

我不同意。 OP所说的是他正常化,因为他被教导总是正常化。我认为这意味着他没有被教导利益和权衡。【参考方案3】:

其他人已经提供了一些好点,您可能还想看看this。

我想再提一个经常被忽略的方面:I/O 往往是大多数查询成本中最大的组成部分,而非规范化通常会增加数据的存储大小,因此使 DBMS 缓存“更小”。

如果您的规范化数据库适合缓存而非规范化不适合,您实际上可能会观察到后者的性能下降

除非您实际上拥有与生产类似的数据量,否则您将无法在开发中发现这一点。这就是为什么您永远不应该在没有可靠测量(在代表性数据量上)的情况下进行非规范化来证明它的众多原因之一。

【讨论】:

以上是关于性能提升与规范化表? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Linux上MySQL优化提升性能 哪些可以优化的关闭NUMA特性

3 万字,关系型数据库性能体系,设计和效率提升

3 万字,关系型数据库性能体系,设计和效率提升

SqlServer性能优化分割提升性能分布式视图

关于MySQL的一些骚操作——提升正确性,抠点性能

提升 Apache Hudi Upsert 性能的三个建议