非规范化以何种方式提高数据库性能?

Rom*_*man 58 database performance database-design normalization denormalization

我听到很多关于非规范化的内容,这是为了提高某些应用程序的性能.但我从未试图做任何相关的事情.

所以,我只是好奇,归一化数据库中的哪些位置会使性能变差,换句话说,什么是非规范化原则?

如果我需要提高性能,我该如何使用这种技术?

Pas*_*TIN 84

非规范化通常用于:

  • 避免一定数量的查询
  • 删除一些连接

非规范化的基本思想是,您将添加冗余数据,或者将一些数据分组,以便能够以更低的成本更轻松地获取这些数据; 哪个更适合表演.


一个简单的例子?

  • 考虑博客的"帖子"和"评论"表
    • 对于每个帖子,您将在"评论"表格中有几行
    • 这意味着要显示具有相关评论数量的帖子列表,您必须:
      • 执行一个查询以列出帖子
      • 每个帖子做一个查询来计算它有多少评论(是的,那些可以合并为一个,以便一次获得所有帖子的数量)
      • 这意味着几个查询.
  • 现在,如果在"帖子"表中添加"评论数量"字段:
    • 您只需要一个查询来列出帖子
    • 并且无需查询"注释"表:注释的数量已经针对"帖子"表进行了非规范化.
    • 并且只有一个返回一个字段的查询比更多查询更好.

现在,有一些成本,是的:

  • 首先,这会占用磁盘和内存中的某些位置,因为您有一些冗余信息:
    • 注释数存储在Posts表中
    • 您还可以在"评论"表中找到这些数字
  • 其次,每当有人添加/删除评论时,您必须:
    • 当然,保存/删除评论
    • 但是,也请更新帖子表中的相应数字.
    • 但是,如果你的博客有更多的人阅读而不是写评论,这可能不是那么糟糕.

  • 很好的例子,大多数人只想"加入"几张桌子. (3认同)
  • +1这是我在去标准化方面遇到的最好的例子之一,非常感谢你,希望我能为它做+10 (2认同)

ewe*_*nli 70

非规范化是一种时空权衡.规范化数据占用的空间较少,但可能需要连接才能构建所需的结果集,因此需要更多时间.如果它被非规范化,则数据在几个地方被复制.然后它需要更多的空间,但是可以随时获得所需的数据视图.

还有其他时空优化,例如

  • 非规范化的观点
  • 预先计算的列

与任何此类方法一样,这可以改善读取数据(因为它们很容易获得),但更新数据变得更加昂贵(因为您需要更新复制或预先计算的数据).

  • 这也是一个更新异常问题.正确规范化的DB可以更新而不会发生奇怪的事情.非规范化数据库具有重复数据; 对一个副本的更新将会出现异常. (17认同)
  • 如果没有提供一种自动更新非规范化数据变化的方法,就不应该进行非规范化.因此,如果将用户名存储在两个位置,则需要触发器以确保它们保持同步.这将防止S. Lott所谈论的问题,并且是大多数人忘记做的事情. (9认同)
  • DAvid,这不是真正的非规范化,这是预期的设计.如果客户名称更改或地址更改或订购的零件价格发生变化,订单不应更改.Orders表记录了一个时刻. (3认同)

Wal*_*tty 11

"非规范化"一词导致设计问题混乱.试图通过非规范化获得高性能数据库就像试图通过远离纽约来到达目的地.它没有告诉你走哪条路.

您需要的是一个好的设计学科,即使该设计有时会与规范化规则相冲突,也能产生简单而完善的设计.

一个这样的设计学科是星型模式.在星型模式中,单个事实表充当表格星的中心.其他表称为维度表,它们位于模式的边缘.尺寸通过看起来像车轮辐条的关系连接到事实表.星型模式基本上是一种将多维设计投影到SQL实现上的方法.

与星型模式密切相关的是雪花模式,这有点复杂.

如果你有一个好的星型模式,你将能够获得各种各样的数据组合,只需要一个三向连接,包括两个维度和一个事实表.不仅如此,许多OLAP工具还能够自动解读您的星形设计,并为您提供点击,向下钻取和图形分析访问您的数据,无需进一步编程.

星型模式设计偶尔会违反第二和第三种常规形式,但它会为报告和摘录提供更快的速度和灵活性.它最常用于数据仓库,数据集市和报告数据库.你通常会从星型模式或其他一些面向检索的设计中得到更好的结果,而不仅仅是偶然的"非规范化".


HLG*_*GEM 7

非规范化的关键问题是:

  • 决定要复制哪些数据以及原因
  • 规划如何保持数据同步
  • 重构查询以使用非规范化字段.

最简单的非规范化类型之一是将标识字段填充到表中以避免连接.由于身份不应该改变,这意味着很少出现保持数据同步的问题.例如,我们将客户端ID填充到多个表中,因为我们经常需要按客户端查询它们,并且在查询中不一定需要表中的任何数据,这些数据将位于客户端表和我们要查询的表之间如果数据完全正常化.您仍然必须执行一个连接以获取客户端名称,但这比连接到6个父表以获取客户端名称更好,因为这是您要查询的表外部所需的唯一数据.

但是,除非我们经常查询需要来自干预表的数据,否则没有任何好处.

另一种常见的非规范化可能是向其他表添加名称字段.由于名称本质上是可更改的,因此您需要确保名称与触发器保持同步.但是,如果这样可以节省您加入5个表而不是2个表,那么插入或更新稍长的成本就值得.