8

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

7 回答 7

6

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

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

于 2009-10-15T21:34:34.423 回答
6

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

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

于 2009-10-15T21:34:48.933 回答
6

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

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

于 2009-10-15T21:51:09.207 回答
3

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

处理“超标准化”数据

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

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

于 2009-10-15T21:33:35.770 回答
3

Well, what about the performance? If the performance is okay, just make the five table JOIN into a view and, for sanity, SELECT from the view when you need the data.

State abbreviations are one of the cases in which I think meaningful keys are okay. For very simple lookup tables with a limited number of rows and where I'm in complete control of the data (meaning it's not populated from some outside source) I'll sometimes create meaningful four or five character keys so that the key value can proxy for the fully descriptive lookup value in some queries.

于 2009-10-16T01:35:00.053 回答
3

Create a view (or inline table-valued function to get parameterization). In any case, I usually put all my code into SPs (some code generated) whether they use views or not and that's that, you pretty much only ever write the join once.

于 2009-10-16T01:39:24.013 回答
2

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

于 2009-10-16T01:19:41.610 回答