簡體   English   中英

SQL主鍵

[英]SQL Primary Keys

因此,我和一位同事正在爭論哪種方式更適合生成GUID的主鍵。

我們使用帶有實體4的.NET 4.0並使用存儲過程來進行選擇/插入/更新。

他希望在代碼中創建GUID主鍵,並使用Guid類或/和使用一些創建的Sequential GUID類將其作為插入的一部分傳回。

我希望使用newid()或newsequentialid()在插入時由SQL Server創建GUID。

我反對他的方式的論點是,如果你必須進行多次插入,你必須進行往返以獲得每個插入的guid,以便為外鍵約束維護該關系。 另外,使用這種方式,您必須為每個插入物進行幾次往返。

他關於使用SQL做的論點是,在插入發生之前他無法訪問密鑰,並且必須等待插入才能使主鍵guid重新用於代碼的其他部分。 這樣,您可以與存儲過程建立一個連接,並處理所有插入。

那么,哪種方法更適合單個插入? 哪種方法更適合事務中的多個插入?

GUID似乎是您主鍵的自然選擇 - 如果您真的必須,您可能會爭辯將其用於表的PRIMARY KEY。 我強烈建議不要使用GUID列作為群集密鑰 ,默認情況下SQL Server會執行此操作,除非您明確告知不要這樣做

你真的需要分開兩個問題:

1) 主鍵是一個邏輯結構 - 一個候選鍵,它唯一且可靠地標識表中的每一行。 這可以是任何東西,真的 - 一個INT,一個GUID,一個字符串 - 選擇對你的場景最有意義的東西。

2) 聚類鍵 (在表上定義“聚簇索引”的一列或多列) - 這是一個與物理存儲相關的東西,這里,一個小的,穩定的,不斷增加的數據類型是你最好的選擇 - INT或BIGINT作為默認選項。

默認情況下,SQL Server表上的主鍵也用作群集鍵 - 但這不一定是這樣! 我個人看到將以前的基於GUID的主/群集密鑰分解為兩個單獨的密鑰 - GUID上的主(邏輯)密鑰和單獨的INT IDENTITY上的群集(排序)密鑰(1, 1)專欄。

正如Kimberly Tripp--索引女王 - 和其他人已多次聲明 - GUID因為聚類鍵不是最佳的,因為由於其隨機性,它將導致大量頁面和索引碎片以及通常不良的性能。

是的,我知道 - 在SQL Server 2005及更高版本中有newsequentialid() - 但即使這樣也不是真正完全順序的,因此也會遇到與GUID相同的問題 - 只是不那么突出。 如果你堅持使用GUID,那么至少在服務器上使用newsequentialid()方法!

然后還有另一個需要考慮的問題:表格上的聚類鍵也會添加到表格中每個非聚集索引的每個條目上 - 因此您確實希望確保它盡可能小。 通常,對於絕大多數表來說,具有2億行的INT應該足夠 - 並且與作為群集密鑰的GUID相比,您可以在磁盤和服務器內存中節省數百兆的存儲空間。

快速計算 - 使用INT與GUID作為主要和群集密鑰:

  • 基表有1'000'000行(3.8 MB對15.26 MB)
  • 6個非聚簇索引(22.89 MB對91.55 MB)

總計:25 MB對106 MB - 這只是在一張桌子上!

還有一些值得深思的東西 - 金佰利特里普的優秀作品 - 閱讀,再讀一遍,消化它! 這是SQL Server索引福音,真的。

當我有這樣的問題時,我對自己說“SQL Server擅長集合,所以讓它讓它做得好”,有時“1只是N的特定情況”。

單個刀片哪種方法更好?

對於同步sql調用的任何一種方法,單個插入時間都是相同的。 然而,“他的”方法會給你帶來更多問題,因為他的順序guid方法不會像sql服務器一樣 (你可能會失去全局唯一性)。 當您不可避免地需要進行多次插入時,它還會拆分您的代碼庫。

哪種方法更適合事務中的多個插入?

如果您正在爭論基於集合的插入(插入/選擇)與單行插入(插入),基於集合將在多個插入上獲勝,因為返回到客戶端的行程將是昂貴的部分。

如果這是我,我將創建一個SP,其中包含要插入的對象的序列化集合,使用輸出子句執行insert / select,在此頁面上查看“示例B.使用帶有標識和計算列的OUTPUT”,讓sql server創建GUID(如果你被卡在上面)並返回到客戶端或運行SP中的下一個語句,根據insert生成的輸出表插入子行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM