我正在设计一个基于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
...
所以我的想法是,我们不必创建单独的Manufacturers
,OwnershipType
,Model
等表格,因为我们并不真正需要关于这些值的任何其他信息,而不是它们的值。目前我已经定义了大约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.ResourceItems
到oms.KeyTypeValues
的外键关系。我还在oms.KeyTypeValues.Id
列上设置了非唯一,非群集索引。我重建了它们以消除碎片。
作为测试,我在KeyTypes
架构中创建了单独的KeyTypeValues
和res
表,并加载了RES_OWNERSHIP_TYPES
个值并加入了它,并且执行时间已经过去了回到大约17秒。我宁愿不把它拿出去,因为它有点挫败了我的目的,似乎在一个更大的问题上放了一个创可贴。
我无法确定为什么只有这个加入会有如此大的打击,并希望有人可能洞察我可能会忽略的东西。如果需要,我很乐意分享更多的数据库设计。
答案 0 :(得分:1)
我建议您使用sub-query
代替JOIN
有时,如果查找表很小(如查找表所示),sub-query
的工作速度比JOIN
但是我们没有实际数据且没有执行计划,所以你应该尝试不同的答案作为建议,看看哪个适合你。
如果这不起作用,请尝试在引用字段上添加索引(除了引用的字段)。
顺便说一句,我不认为你的设计很糟糕。我在许多不同的系统中都看到过这样的查找表。答案 1 :(得分:0)
如果向具有3条记录的表添加联接会显着影响您的性能,则意味着通过添加该联接,查询计划会发生显着变化。
尝试快速而肮脏的事情是一次性运行sp_updatestats
以查看是否能解决您的问题(我认为它可能会解决)。这将告诉SQL Server更新所有表和索引的统计信息,并帮助它更好地选择查询计划。
更彻底的解决方案是比较查询的两个变体的执行计划,以了解为什么性能正在受到影响。这应该阐明如何提高绩效。我不建议删除表并进入仅代码枚举。如果事情正常,加入额外的表格时应该没有明显的性能差异。