替代密钥与EF的自然密钥

时间:2013-11-18 16:30:30

标签: sql entity-framework tsql database-design

我的同事和我正在尝试确定哪种方法可以更好地设计两个数据库表的架构和密钥。一个是很少改变的查找表。它有大约700行。另一个表引用查找表。随着时间的推移,这个表将有数千行。在设计B中,查找表具有由3个varchars组成的主键。另一个表有一个主键,由相同的3个varchars组成,并添加了两个日期字段。在设计A中,3个varchars被替换为代理键。 3个varchars对它们有唯一约束(UC)。

哪个更好的设计?我的同事说,如果我们有一个代理键,当我们需要向用户显示数据时,在表上进行连接会使这非常慢。此外,拥有仅用于使行唯一的密钥是浪费的。我的论点是连接速度很快,为3个varchars存储额外的数据是浪费的,因为它在两个表中复制了这些数据。

我们在T-SQL Server 2008中使用EF 5的WPF桌面应用程序中使用它。代理键或自然键?附图显示了两种不同的设计。

enter image description here

1 个答案:

答案 0 :(得分:4)

桌子上只有几千行,我认为你不会发现任何差异。即使一个表有数百万行,另一个表只有700个。而SQL-Server几乎被设计为有效地进行连接,所以当你声称连接到一个时,你的同事是不正确的。相当小(700行)的表会影响效率。

设计A优于B的一个方面是较大的表(PriceIndex)将更窄,因此是用于加入的索引。 4个字节而不是90个字节可以大大提高性能。在设计A中,您可能需要的包含代理键的所有其他复合索引也将比在B中更窄。

设计B比A更有效的情况是涉及两个表中GROUP BY列的查询。例如,如果您有GROUP BY Price, HubCode的查询,则在设计B中您可以在这两个列上添加复合索引,而在设计A中,列将位于单独的表中,您不能拥有包含2的列的索引表。

另一个方面是,是否有其他表将这些列作为主键,例如,如果您有另一个表(HubCode)作为PK而另一个表使用(HubCode, TimeFrame)而另一个表(IndexCode, HubCode)和可能是另一个(IndexCode, HubCode, TimeFrame, StartDate, EndDate, CustomerID)。使用设计B(所有表具有自然键),涉及来自多个表的连接的若干复杂查询可以更有效,因为可以消除一些中间连接。使用设计A(代理键),当(中间)表很大时,不能跳过中间连接并且查找成本会变得非常大。

最后,没有什么比测试您的数据以及您希望表格增长的大小以及您希望运行的查询类型更重要。