问题数据库设计导致性能问题

时间:2017-03-02 16:22:17

标签: sql-server tsql database-design sql-server-2014 query-performance

我正在设计一个基于C#/ SQL Server的多模块应用程序。我的设计是在名为KeyTypeValues的表中保存所有通用查找值。该表与KeyTypes相关,它定义了它的数据类型。

例如:

oms.KeyTypes
------------
Id          INT NOT NULL IDENTITY(1,1) PRIMARY KEY
KeyTypeName VARCHAR(40) NOT NULL
...

oms.KeyTypeValues
-----------------
Id                  INT NOT NULL IDENTITY(1,1) PRIMARY KEY
KeyTypeId           INT NOT NULL (FOREIGN KEY to oms.KeyTypes Id)
KeyTypeValueMeaning VARCHAR(80) NOT NULL
...

oms.KeyTypes样本数据:

Id KeyTypeName         KeyTypeDescription
-- -----------         ------------------
1  RES_MFGS            Resource Manufacturers
2  RES_OWNERSHIP_TYPES Resource Ownership Types
...

oms.KeyTypeValues样本数据:

Id KeyTypeId KeyTypeValueMeaning
-- --------- -------------------
1  1         Ford
2  1         Chevrolet
3  2         Owned
4  2         Leased
...

所以我的想法是,我们不必创建单独的ManufacturersOwnershipTypeModel等表格,因为我们并不真正需要关于这些值的任何其他信息,而不是它们的值。目前我已经定义了大约88个,设计对我来说效果很好。

我正在处理从名为res.ResourceItems的表加入时遇到性能问题的问题查询。我必须将它加入KeyTypeValues表6次以进行不同的查找。

ResourceItems定义的一部分:

res.ResourceItems
-----------------
Id               INT NOT NULL IDENTITY(1,1) PRIMARY KEY
OwnsershipTypeId INT NOT NULL
ManufacturerId   INT NOT NULL
...

如果我消除了我的问题密钥类型(RES_OWNERSHIP_TYPES),我可以将其打开并在大约17秒内将70多个列拉回~112,000行。表演并不是很棒,但考虑到我必须加入另外9张桌子,这是可以接受的。但是,当我添加连接以检索RES_OWNERSHIP_TYPES时,执行时间会跳到45秒。此时RES_OWNERSHIP_TYPES键类型只有3个可能的值,而oms.KeyTypeValues只有大约3,000条记录。随着我们为正在构建的系统增加更多内容,它将随着时间的推移继续缓慢增长。

我意识到将所有权类型拉出来并创建enum将是一种更有效的方法来解决这个问题,因为我们不太可能拥有所有权类型;但是,我对整体设计感到担忧,因为它有如此巨大的性能影响。

对于所有Id值,我确实拥有从res.ResourceItemsoms.KeyTypeValues的外键关系。我还在oms.KeyTypeValues.Id列上设置了非唯一,非群集索引。我重建了它们以消除碎片。

作为测试,我在KeyTypes架构中创建了单独的KeyTypeValuesres表,并加载了RES_OWNERSHIP_TYPES个值并加入了它,并且执行时间已经过去了回到大约17秒。我宁愿不把它拿出去,因为它有点挫败了我的目的,似乎在一个更大的问题上放了一个创可贴。

我无法确定为什么只有这个加入会有如此大的打击,并希望有人可能洞察我可能会忽略的东西。如果需要,我很乐意分享更多的数据库设计。

2 个答案:

答案 0 :(得分:1)

我建议您使用sub-query代替JOIN

有时,如果查找表很小(如查找表所示),sub-query的工作速度比JOIN

但是我们没有实际数据且没有执行计划,所以你应该尝试不同的答案作为建议,看看哪个适合你。

如果这不起作用,请尝试在引用字段上添加索引(除了引用的字段)。

顺便说一句,我不认为你的设计很糟糕。我在许多不同的系统中都看到过这样的查找表。

答案 1 :(得分:0)

如果向具有3条记录的表添加联接会显着影响您的性能,则意味着通过添加该联接,查询计划会发生显着变化。

尝试快速而肮脏的事情是一次性运行sp_updatestats以查看是否能解决您的问题(我认为它可能会解决)。这将告诉SQL Server更新所有表和索引的统计信息,并帮助它更好地选择查询计划。

更彻底的解决方案是比较查询的两个变体的执行计划,以了解为什么性能正在受到影响。这应该阐明如何提高绩效。我不建议删除表并进入仅代码枚举。如果事情正常,加入额外的表格时应该没有明显的性能差异。