1

我正在設計一個基於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 
... 

這樣的想法是,我沒有創建單獨的ManufacturersOwnershipType,Model等等表格除了它們的值之外,並不需要任何關於這些值的附加信息。目前我已經定義了大約88個,並且設計對我來說效果很好。

我正在處理從名爲res.ResourceItems的表加入時出現性能問題的問題查詢。我必須將它加入到KeyTypeValues表中,以進行不同的查找。

ResourceItems定義的一部分:

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

如果我消除了我的問題關鍵型(RES_OWNERSHIP_TYPES),我可以運行它敞開,它拉回來〜112000點的行與列70 +在17秒左右。表現並不出色,但考慮到我不得不加入9個附加表格,這是可以接受的。但是,當我添加聯接以檢索RES_OWNERSHIP_TYPES時,執行時間跳至45秒。 RES_OWNERSHIP_TYPES密鑰類型此時只有3個可能的值,而oms.KeyTypeValues只有約3,000個記錄。隨着我們對正在構建的系統添加更多內容,它將會隨着時間的推移而繼續增長。

我意識到,取消所有權類型並創建enum反而會是一種更有效的方式來處理此問題,因爲我們不太可能擁有所有權類型;然而,我擔心這種戲劇性表現會受到影響。

對於所有的Id值,我的外鍵關係從res.ResourceItemsoms.KeyTypeValues。我還在oms.KeyTypeValues.Id列中設置了非唯一,非聚集索引設置。我已經重建它們以消除碎片。

作爲一個測試,我在res模式中創建單獨KeyTypesKeyTypeValues表和加載只是RES_OWNERSHIP_TYPES值,並加入到它,並且執行時間又回到了17秒左右。我寧願不這樣做,因爲它有點挫敗我的目的,似乎是在更大的問題上提供創可貼。

我無法確定爲什麼會有這麼大的打擊,希望有人能夠洞察我可能忽略的內容。如果需要,我很樂意分享更多的數據庫設計。

+0

考慮使用[覆蓋索引](http://www.dbadiaries.com/sql-server-covering-index-and-key-lookup/)。請注意,SQL Server 2005及更高版本支持[包含列](http://msdn.microsoft.com/zh-cn/library/ms190806.aspx)以及組合索引。 – HABO

回答

0

如果向具有3條記錄的表中添加連接會顯着影響您的性能,這意味着查詢計劃隨着該連接的添加而顯着變化。

試圖快速和骯髒的事情是一次運行sp_updatestats,看看是否能解決您的問題(我認爲它可能會)。這將告訴SQL Server更新所有表和索引的統計信息,並幫助它在查詢計劃中做出更好的選擇。

更徹底的解決方案是比較查詢的兩個變體的執行計劃,以瞭解爲什麼性能正在受損。這應該闡明如何提高性能。我不建議刪除表格並僅使用代碼枚舉。如果事情工作正常,加入該額外表格時應該沒有明顯的性能差異。

+0

我做了你和@FRICKER的建議,都有所幫助。簡單地運行'sp_updatestats'影響最大,回落時間不到20秒。添加額外的索引並使用子查詢再削減幾秒鐘,所以現在兩個查詢都是相同的。 – bassrek

1

我建議你使用sub-query代替JOIN

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

但是我們沒有實際的數據和唐沒有執行計劃,所以你應該嘗試不同的答案作爲建議,看看哪一個適合你。

如果這不起作用,請嘗試在引用字段(除引用字段之外)上添加索引。

順便說一句,我不認爲你的設計是壞的。我在許多不同的系統中看到過這樣的查找表。

+0

謝謝 - 我希望我可以將你的和@Tim標記爲答案;然而,更新統計數據似乎是最大的罪魁禍首。我使用子查詢和附加索引進行了實驗,並且我能夠縮短几秒鐘的時間。感謝您對設計的評論 - 是的,我在不同的系統中使用過這種設計,我認爲這很好。 – bassrek

+0

使統計數據保持最新始終是件好事。感謝您的投票:) – FLICKER