Sql 为健全或性能进行非规范化?

Sql 为健全或性能进行非规范化?,sql,denormalization,normalize,Sql,Denormalization,Normalize,我开始了一个新项目,他们有一个非常规范化的数据库。可以是查找的所有内容都存储为查找表的外键。这是规范化的,很好,但我最终为最简单的查询做了5个表连接 from va in VehicleActions join vat in VehicleActionTypes on va.VehicleActionTypeId equals vat.VehicleActionTypeId join ai in ActivityInvolvements on va.VehicleActi

我开始了一个新项目,他们有一个非常规范化的数据库。可以是查找的所有内容都存储为查找表的外键。这是规范化的,很好,但我最终为最简单的查询做了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}
我想建议我们去规范化一些东西。就像州法典一样。在我的有生之年,我看不到州代码发生变化。类似的故事与三个字母的机构代码。这些都是由代理机构分发的,永远不会改变

当我向DBA提出状态代码问题和5表联接时。我得到的回答是“我们正常化了”和“连接很快”

是否有令人信服的理由去规范化?如果没有别的事,我会为了理智而做的

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))

之前的这篇文章处理了一个与您所遇到的问题类似的问题。希望它能对你有所帮助

我个人对规范化的看法是尽可能地规范化,但非规范化只是为了性能。而evn性能的非规范化是需要避免的。在我去规范化之前,我会先进行分析,设置正确的索引等等


理智。。。这被高估了。尤其是在我们这个行业

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


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

请注意不要想根据您当前的习惯习惯来进行调整。目前,不熟悉的代码似乎不适合您的理解。随着时间的推移,你可能会变得适应


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

我甚至不知道我是否会将你想做的事情称为非规范化——看起来你只是想用自然外键替换人工外键(StateId、AgencyId)(州缩写,机构代码)。使用varchar字段而不是整数字段会降低联接/查询性能,但是(a)如果您大部分时间都不需要联接表,因为自然FK是您想要的,这没什么大不了的(b)您的数据库需要相当大/有很高的负载才能引人注目


但djna是正确的,在做出这样的改变之前,你需要完全了解当前和未来的需求。你确定三个字母的机构代码永远不会改变,即使从现在起五年也不会改变吗?真的,真的确定吗?

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

那么,性能如何呢?如果性能正常,只需将五个表连接到一个视图中,为保持理智,请选择fro当您需要数据时,我会查看视图


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

创建一个视图(或内联表值函数以获得参数化)。在任何情况下,我通常将所有代码放入SPs中(生成一些代码)无论他们是否使用视图,也就是说,您几乎只编写一次联接。

+1指出开发人员往往会随着时间的推移而增长。我认为在这种情况下,最好学会处理超规范化数据并进行调整,而不是将数据调整到我们满意的程度。+1表示“理智”soundbite。介意我偶尔引用你的话吗?;-)小的、简单的、可重用的函数的想法应该适用于所有我们认为正确的代码,如果可能的话。对于这样的事情,我从表值函数和视图中获得了很多好处。另外,报告也变得容易多了。我曾经非常喜欢自然外键的优雅、逻辑和清晰,但它们不值得经常维护。因此,我创造了优雅的工具来管理人工钥匙,每个人都能及时回家吃饭。