【发布时间】:2017-07-22 11:39:55
【问题描述】:
我正在设计一个基于 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 秒内拉回约 112,000 行和 70 多列。性能不是很好,但考虑到我必须加入 9 个额外的表,这是可以接受的。但是,当我添加连接以检索 RES_OWNERSHIP_TYPES 时,执行时间会跳到 45 秒。 RES_OWNERSHIP_TYPES 键类型此时只有 3 个可能的值,oms.KeyTypeValues 总共只有大约 3,000 条记录。随着我们向正在构建的系统添加更多内容,它将随着时间的推移继续缓慢增长。
我意识到,将所有权类型拉出并创建一个enum 将是一种更有效的方式来处理这个问题,因为我们不太可能拥有更多的所有权类型;但是,我关心的是整体设计会带来如此巨大的性能冲击。
对于所有 Id 值,我确实有从 res.ResourceItems 到 oms.KeyTypeValues 的外键关系。我还在oms.KeyTypeValues.Id 列上设置了非唯一、非聚集索引。我已经重建它们以消除碎片。
作为测试,我在 res 架构中创建了单独的 KeyTypes 和 KeyTypeValues 表,并仅加载了 RES_OWNERSHIP_TYPES 值并加入它,执行时间回到了大约 17 秒。我宁愿不执行此操作,因为它有点违背我的目的,并且似乎是在为更大的问题贴上创可贴。
我无法确定为什么仅通过该连接会产生如此大的影响,并希望有人能洞察我可能忽略的内容。如果需要,我很乐意分享更多的数据库设计。
【问题讨论】:
-
考虑使用covering indexes。请注意,SQL Server 2005 及更高版本支持included columns 以及复合索引。
标签: sql-server tsql database-design sql-server-2014 query-performance