代码之家  ›  专栏  ›  技术社区  ›  TheLQ

预计算是非规范化的吗?如果不是,什么是(简单地说)?

sql
  •  4
  • TheLQ  · 技术社区  · 14 年前

    我能想到的唯一一个关于速度的例子是,在我曾经实习过的一个地方,对两个表中的大约2500000行进行计算。正如您所猜测的,计算如此多的按需操作需要花费很长时间,并冻结了我所使用的dev服务器几分钟。所以就在我离开之前,我的主管想让我写一个计算表来保存所有预先计算的值,并且大约每小时更新一次(这是一个不经常使用的内部站点)。然而,我从来没有完成它,因为我离开了

    这是一个非规范化的例子吗?如果是这样的话,这是一个很好的例子,还是走得更远?如果不是,那么简单来说是什么?

    5 回复  |  直到 14 年前
        1
  •  2
  •   Beth    14 年前

    现在你想打印圣诞卡标签给你所有的家庭联系人列出所有的名字,但每个邮寄地址只有一个标签。

    您需要一种方法来链接两个规范化集。这两组数据中的所有数据都是标准化的。它是“原子”,代表一个“原子”,或者一段无法分解的信息。没有一个是重复的。

    此时,您需要在两个集合中引入一个家庭ID来链接它们。每个邮寄地址都有一个householdID,每个联系人都有一个householdID值,可以重复(同住一户的表哥Alan和叔叔Bob有相同的householdID。)

    现在假设我们在工作,我们需要跟踪无数的联系人和家庭。为了便于维护,保持数据的规范化非常好,因为我们只希望在一个地方存储联系人和家庭详细信息。当我们更新一个地址时,我们正在更新所有相关联系人的地址。不幸的是,出于性能方面的考虑,当我们要求服务器加入两个相关的集合时,需要花费很长时间。

    因此,一些开发人员会出现并创建一个包含无数行的非规范化表,每一行对应一个联系人,并重新创建家庭细节。性能提高了,空间的考虑被抛到了窗外,因为我们现在需要3百万行的空间,而不是2行。

        2
  •  1
  •   SQLMenace    14 年前

    我会称之为聚合而不是非规范化(如果它是订单数量,例如,每天的订单总数…)。这就是OLAP的用途。例如,非规范化不是在联系人表中有PhoneType表和PhoneTypeID,而是在联系人表中有PhoneType,这样就消除了1个连接

    当然,您也可以使用索引/物化视图来聚集值…但是现在您将减慢更新、删除和插入的速度

    触发器也是实现这一点的另一种方法

        3
  •  1
  •   MatBailie    14 年前

    在一个过于简化的形式中,我将把非标准化描述为减少用于表示相同数据的表的数量。

    客户和地址通常保存在不同的表中,以允许一个客户有多个地址的概念。(工作、家庭、当前地址、以前的地址等)

    “在正常工作之前进行非标准化”的好处是减少了某些维护和/或处理开销,但坚持与通过制定标准化模型得出的基本模型相同。

    在“姓氏”示例中,通过非规范化,可以根据客户的姓氏和出生日期向其添加索引。如果不去规范化,姓氏和出生日期在不同的表格中,综合指数是不可能的。

        4
  •  0
  •   Chris    14 年前

    去规范化可能是有益的,您提供的示例就是这样一个例子。动态计算这些值是不理想的,因为成本很高,因此您需要创建一个表,并有一个函数id与计算值一起引用另一个表。

        5
  •  0
  •   BillThor    14 年前

    正规形式将拒绝此表,因为它完全可以从现有数据派生。但是,由于性能原因,通常可以找到这种类型的数据。例如,库存盘点通常进行,但可以从创建它们的交易中派生出来。

    如果updatevolumes允许,可以使用触发器来模拟使用表的物化视图。这可以降低维护聚合价值的成本。如果不是这样的话,它会在更长的时间内分散开销。但是,它确实增加了创建死锁条件的风险。