【问题标题】:Denormalizing for sanity or performance?为了理智或性能而去规范化?
【发布时间】:2010-12-07 04:57:52
【问题描述】:

我开始了一个新项目,他们有一个非常规范化的数据库。可以查找的所有内容都存储为查找表的外键。这是规范化的,很好,但我最终为最简单的查询做了 5 个表连接。

    from va in VehicleActions
    join vat in VehicleActionTypes on va.VehicleActionTypeId equals vat.VehicleActionTypeId
    join ai in ActivityInvolvements on va.VehicleActionId equals ai.VehicleActionId
    join a in Agencies on va.AgencyId equals a.AgencyId
    join vd in VehicleDescriptions on ai.VehicleDescriptionId equals vd.VehicleDescriptionId
    join s in States on vd.LicensePlateStateId equals s.StateId
    where va.CreatedDate > DateTime.Now.AddHours(-DateTime.Now.Hour)
    select new {va.VehicleActionId,a.AgencyCode,vat.Description,vat.Code,
vd.LicensePlateNumber,LPNState = s.Code,va.LatestDateTime,va.CreatedDate}

我想建议我们对一些东西进行去规范化。就像州代码一样。在我的一生中,我没有看到州代码发生变化。与 3 个字母的机构代码类似的故事。这些是由代理机构分发的,永远不会改变。

当我以状态代码问题和 5 个表连接联系 DBA 时。我得到“我们已标准化”和“加入速度很快”的响应。

是否有令人信服的非规范化论据?如果没有别的,我会这样做。

T-SQL 中的相同查询:

    SELECT VehicleAction.VehicleActionID
      , Agency.AgencyCode AS ActionAgency
      , VehicleActionType.Description
      , VehicleDescription.LicensePlateNumber
      , State.Code AS LPNState
      , VehicleAction.LatestDateTime AS ActionLatestDateTime
      , VehicleAction.CreatedDate
FROM VehicleAction INNER JOIN
     VehicleActionType ON VehicleAction.VehicleActionTypeId = VehicleActionType.VehicleActionTypeId INNER JOIN
     ActivityInvolvement ON VehicleAction.VehicleActionId = ActivityInvolvement.VehicleActionId INNER JOIN
     Agency ON VehicleAction.AgencyId = Agency.AgencyId INNER JOIN
     VehicleDescription ON ActivityInvolvement.VehicleDescriptionId = VehicleDescription.VehicleDescriptionId INNER JOIN
     State ON VehicleDescription.LicensePlateStateId = State.StateId
Where VehicleAction.CreatedDate >= floor(cast(getdate() as float))

【问题讨论】:

    标签: sql denormalization normalize


    【解决方案1】:

    上一篇文章处理了与您遇到的问题类似的问题。希望对您有所帮助。

    Dealing with "hypernormalized" data

    我个人对规范化的看法是尽可能地规范化,但非规范化只是为了提高性能。甚至性能的非规范化也是要避免的。在我去规范化之前,我会走分析路线、设置正确的索引等。

    理智……这被高估了。尤其是在我们的职业中。

    【讨论】:

    • +1 表示“理智”的声音片段。介意我偶尔引用你的话吗? ;-)
    【解决方案2】:

    出于性能(和理智)的原因,有时可能需要进行一些非规范化。很难看到你所有的桌子/需求等......

    但是为什么不只是构建一些方便的视图(进行一些连接),然后使用它们来编写更简单的查询呢?

    【讨论】:

    • 尽可能小、简单、可重用函数的想法应该适用于我们正确的所有代码。对于这样的事情,我从表值函数和视图中获得了很多好处。作为奖励,报告也变得容易得多。
    【解决方案3】:

    谨防想要根据您当前的习语来塑造事物。现在,不熟悉的代码似乎笨拙且妨碍您理解。随着时间的推移,您可能会适应环境。

    如果当前(或已知的未来)要求(例如性能)没有得到满足,那么这是一个完全不同的问题。但请记住,任何事情都可以进行性能调整,目标不是让事情尽可能快,而是让它们足够快。

    【讨论】:

    • +1 指出开发人员往往会随着时间的推移而成长。我认为在这种情况下,最好学会处理超规范化的数据并进行调整,而不是将数据调整到我们感到满意的程度。
    【解决方案4】:

    我什至不知道我是否会将您想要做的非规范化称为非规范化 - 它看起来更像是您只想用自然外键(State Abbreviation,Agency Code)替换人工外键(StateId,AgencyId)。使用 varchar 字段而不是整数字段会降低连接/查询性能,但是 (a) 如果您大部分时间甚至不需要连接表,因为自然 FK 是您想要的,这没什么大不了的,并且 ( b) 您的数据库需要很大/负载很高才能引人注目。

    但是 djna 是正确的,因为在进行这样的更改之前,您需要全面了解当前和未来的需求。你确定三个字母的机构代码永远不会改变,即使是五年后?真的,真的确定?

    【讨论】:

    • 我曾经是自然外键的优雅、逻辑和清晰的忠实粉丝,但它们不值得不断的维护麻烦。因此,我创建了优雅的工具来管理人工钥匙,并让每个人都能及时回家。
    【解决方案5】:

    如果没有计划如果代码确实发生更改,您将做什么以及您的人工密钥方案将如何解决这种可能性,那么三字母代码可能会更改的论点(对于这种“规范化”)并不是很有说服力比使用代码作为键更好。除非您已经实现了一个完全时态的模式(这非常难以做到,并且您的示例没有建议),否则对我来说,您的规范化对您有什么好处并不明显。现在,如果您与来自多个来源和标准的机构合作,这些机构的代号可能相互冲突,或者如果“州”最终可能意味着州、省、部门、州或州的两个字母代码,那就是另一回事了。然后,您需要自己的密钥,或者您需要一个包含比该代码更多信息的两列密钥。

    【讨论】:

      【解决方案6】:

      那么,性能怎么样?如果性能还可以,只需将五个表 JOIN 放入一个视图中,并且为了理智,在需要数据时从视图中选择。

      状态缩写是我认为有意义的键可以使用的情况之一。对于行数有限且我完全控制数据的非常简单的查找表(这意味着它不是从某些外部来源填充的),我有时会创建有意义的四五个字符键,以便键值可以代理用于某些查询中的完全描述性查找值。

      【讨论】:

        【解决方案7】:

        创建一个视图(或内联表值函数以获取参数化)。无论如何,我通常将我所有的代码放入 SP(生成一些代码),无论它们是否使用视图,就是这样,您几乎只编写一次联接。

        【讨论】:

          猜你喜欢
          • 2012-10-08
          • 2011-02-21
          • 2013-03-29
          • 1970-01-01
          • 2018-10-19
          • 2013-08-21
          • 2010-12-29
          • 1970-01-01
          • 2014-11-16
          相关资源
          最近更新 更多