为了理智还是表现而非规范化?

时间:2009-10-15 21:28:07

标签: sql denormalization normalize

我已经开始了一个新项目,他们有一个非常规范化的数据库。可以查找的所有内容都作为外键存储到查找表中。这是规范化和精细的,但我最终为最简单的查询做了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))

6 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:6)

谨防想要根据你当前的习语来塑造事物。现在,不熟悉的代码似乎不符合你的理解,也阻碍了你的理解。随着时间的推移你可能会适应。

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

答案 2 :(得分:6)

我不知道我是否会调用你想要进行非规范化的东西 - 它看起来更像你只想用自然外键(State Abbreviation,Agency Code)替换人工外键(StateId,AgencyId)。使用varchar字段而不是整数字段会降低连接/查询性能,但是(a)如果你甚至不需要在大多数时间都加入表,因为无论如何它都是你想要的自然FK并不是什么大问题( b)你的数据库需要非常大/有很高的负载才能引起注意。

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

答案 3 :(得分:3)

这篇上一篇文章涉及到与你所拥有的问题类似的问题。希望它对你有所帮助。

Dealing with "hypernormalized" data

我个人对规范化的看法是尽可能规范化,但仅针对性能进行非规范化。并且要避免对性能进行非规范化。在我进行反规范化之前,我会选择分析路径,设置正确的索引等。

理智......那被高估了。特别是在我们的专业。

答案 4 :(得分:3)

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

答案 5 :(得分:2)

如果代码确实发生了变化,那么三字母代码可能会发生变化的参数(对于这种“规范化”)并不十分引人注目,以及人工密钥方案如何解决这种可能性比使用代码作为键更好。除非你已经实现了一个完全时间的模式(这很难做到而且你的例子没有建议),但对我而言,你的规范化对你有什么好处并不明显。现在,如果您与来自多个来源的代理商和可能存在冲突代码名称的标准一起工作,或者“州”可能最终意味着州,省,部门,州或estado的双字母代码,那么这是另一回事。然后,您需要自己的密钥,或者需要一个包含比该代码更多信息的双列密钥。