2012-03-03 44 views
0

我正在嘗試在SQL Server 2008 R2中構建一個數據庫,該數據庫將允許用戶將他們自己的子類型放入類別中。我有一個父表,其中包含預設的類別名稱(由我定義)。當組合鍵存在時,主鍵中不包含唯一ID字段

我面對的問題是什麼是處理PRIMARY KEYUNIQUE約束以及外鍵參考的最佳方法。因爲我預計子表(我們稱之爲CategoryTypes)隨着時間的推移會變得相當大,並且需要能夠有效地允許基於父表(Categories)從數據中讀取數據,所以索引是其中心。我需要預測是否有任何問題需要預測表格是否如下佈置:

我擔心CategoryTypes表中的IDENTITY列需要維護一個唯一的計數。我包含這個字段的原因是在應用程序中的層之間傳遞數據時允許更簡單的引用。通過傳遞整數與整數/字符串對。這些表中的數據將保留在數據庫的每一層以節省帶寬。從數據庫的角度來看,下面的佈局是否會在部署後面臨任何重大挑戰?

爲了簡化,使用複合鍵存在時未包含在主鍵中的唯一ID字段(IDENTITY)是否存在問題?見下面表格佈局:

父表:

CREATE TABLE schema.Categories 
(
    Id TINYINT PRIMARY KEY NOT NULL, 
    Name VARCHAR(100) NOT NULL, 
) 

分臺(一段時間內的用戶插入的數據):

CREATE TABLE schema.CategoryTypes 
(
    Id INT IDENTITY(1,1) NOT NULL, 
    CategoryId TINYINT REFERENCES schema.Categories(Id) NOT NULL, 
    Name VARCHAR(100) NOT NULL, 
    CONSTRAINT PRIMARY KEY CLUSTERED(CategoryId, Name) 
    CONSTRAINT UC_CategoryTypesId UNIQUE NONCLUSTERED(Id) 
) 
+0

PS - 我還要補充的是,標識在子表「CategoryTypes」將被其他表作爲通過外鍵關係引用...所以它是必要的。我願意接受任何解決餐桌設計複雜問題的最佳實踐。 – 2012-03-03 20:03:08

+1

請注意,集羣表中的次要索引是昂貴的。如果您確實不需要代理鍵'{Id}',那麼請不要使用它,只需使用自然鍵'{CategoryId,Name}'。如果你想要兩個鍵,使用一個基於堆的表(即'PRIMARY KEY NONCLUSTERED')。 – 2012-03-04 02:14:25

+0

Branko,我知道額外的開銷,但是謝謝你在這種情況下重申這一點。我面臨的挑戰是我知道我需要引用代理ID(外鍵)。我想你可以做一個複合外鍵......但我對此並不是很熟悉。代理似乎讓事情變得更容易。也就是說,我可以從消除「CLUSTERD」索引開始,贊成「NONCLUSTERED」,因爲你和Justin都建議。如果稍後需要性能,在獲得一些生產數據後,我總是可以解決性能問題。在CRUD中 - 聚集索引有助於「閱讀」,但可以投入開銷。 – 2012-03-04 17:27:19

回答

0

你所描述有點像繼承結構的聲音。據我瞭解,我創建了一個示例數據集。你能證實這是你的意圖嗎?

如果是這樣,那麼這應該工作得很好,我不明白你爲什麼不將CategoryType.Id設置爲主鍵?如果這不是你的PK,也不是在別處被引用爲FK,那麼我沒有看到它的一個指向。我個人不認爲你在帶寬節省方面獲得了足夠的收入,而且應該只需按照CategoryId和Name來請求數據。事實上,沒有PK往往是如何表示繼承結構(How can you represent inheritance in a database?)。

如果你必須保持它的設置方式,我個人建議將ID設置爲PK,並且對CategoryId/Name設置唯一的約束。

雖然這只是我的兩分錢。

Category 
---- 
Id|Name 
1 |Food 
2 |Drink 

CategoryType 
---- 
Id|CategoryId|Name 
1 |2   |Water 
2 |2   |Orange Juice 

修訂ANSWER(直接解決性能問題)

首先,我建議並不完全不用擔心太多,如果它是沒有問題的。這是我們許多人制造的常見問題,過分複雜的東西不需要它。在我的書落在下KISS principle

但是,如果你是在試圖向你解釋的方式提前算出這個時間deadset,那麼這裏有我更多的想法:

  • 創建PK爲ID ,但是使其成爲非專有
  • 在CategoryId上創建聚類索引,並考慮在上述非聚集索引上使用INCLUDE keyword
  • 只有做,如果你更經常將要使用的類別編號查詢以上,比CategoryType.Id
  • 一個考慮創建密鑰時,雖然(甚至從INCLUDE文章所)
Index maintenance may increase the time that it takes to perform modifications 
, inserts, updates, or deletes, to the underlying table or indexed view. 

最終,我認爲你正在做的事情會很好,但是PK沒有必要聚集,所以我肯定會把PK移到Id字段。如果要在CategoryId或CategoryId/Name上創建羣集,或者如果您想按照我的建議嘗試使用INCLUDE,那麼這是您的選擇。這實際上取決於表的使用方式,因此比較執行計劃可能對此有所幫助。

希望這有助於:)

+0

賈斯汀,回答你的問題「這是一種繼承結構」 - 是的。你制定的例子與我試圖做的完全相似。您對使Id成爲PK的評論是我目前在SQL中實現的結構。我之所以反其道而行之所以這樣做,是因爲索引(例如,當你有一百萬個CategoryTypes時,根據複合關係有沒有獲得聚集索引?我同意PK似乎是最合乎邏輯的意義在這裏作爲Id ...但考慮到PK與Unique Clustered Key非常相似,我想知道哪種方式最適合perf。 – 2012-03-03 20:35:01

+0

編輯我的回覆,將它重點放在更具體的問題上。 – 2012-03-04 03:02:07

相關問題