簡體   English   中英

SQL Server - Guid VS. 長

[英]SQL Server - Guid VS. Long

到目前為止,我一直在使用C#“Guid = Guid.NewGuid();” 生成唯一ID的方法,該ID可以使用Linq to SQL存儲在我的某些SQL Server數據庫表中作為ID字段。 我被告知,出於索引的原因,使用GUID是一個壞主意,我應該使用自動遞增Long。 將使用長時間加速我的數據庫事務? 如果是這樣,我該如何生成Long類型的唯一ID?

問候,

兩者都有利有弊,這完全取決於你如何使用它們。

如果您需要可以跨多個數據庫工作的標識符,您需要GUID。 Long有一些技巧(手動為每個數據庫分配不同的種子/增量),但這些技巧不能很好地擴展。

就索引而言,如果索引是聚簇的,Long將提供更好的插入性能(默認情況下,主鍵是聚簇的,但可以為您的表修改),因為在每次插入后都不需要重新組織表。

然而,就並發插入而言,Long(標識)列將比GUID慢 - 標識列生成需要一系列獨占鎖以確保只有一行獲得下一個序列號。 在許多用戶一直插入許多行的環境中,這可能會影響性能。 在這種情況下GUID生成更快。

存儲方面,GUID占用了Long的兩倍空間(8字節對16)。 但是,如果8個字節在一個葉子中適合多少條記錄,從而在平均請求期間從磁盤中提取的葉子數量會產生顯着差異,則它取決於行的整體大小。

一個long(sql server中的大int)是8個字節,Guid是16個字節,因此你在查找時將sql server必須比較的字節數減半。

要生成long,請在數據庫中創建字段時使用IDENTITY(1,1)。

所以使用create table或alter table:

Field_NAME BIGINT NOT NULL PRIMARY KEY IDENTITY(1,1)

查看將Linq發布到sql的注釋

“索引女王” - 金·特里普 - 在她的索引博客文章中基本上都說明了這一點:

基本上,她的最佳實踐是:最佳聚類鍵應該是:

  • 獨特
  • 穩定(永不改變)
  • 不斷增加

GUID違反了“小”和“不斷增加”,因此不是最佳選擇。

PLUS:所有聚類鍵都將添加到每個非聚集索引中的每個單獨條目中(作為查找以實際查找數據庫中的記錄),因此您希望使它們盡可能小(INT = 4字節與GUID = 16字節)。 如果你有數億行和幾個非聚集索引,那么在GUID上選擇INT或BIGINT可以產生很大的不同 - 即使只是在空間方面。

你可以整天辯論GUID或身份。 我更喜歡數據庫生成帶有標識的唯一值。 如果合並來自多個數據庫的數據,請添加另一列(以標識源數據庫,可能是tinyint或smallint)並形成復合主鍵。

如果您確實使用了標識,請確保根據您將生成的預期密鑰數選擇正確的數據類型:

bigint - 8 Bytes - max positive value: 9,223,372,036,854,775,807  
int    - 4 Bytes - max positive value:             2,147,483,647

注意“預期鍵數”與行數不同。 如果您主要添加並保留行,您可能會發現INT足夠超過20億個唯一鍵。 我打賭你的桌子不會那么大。 但是,如果你有一個高容量表,你不斷添加和刪除行,你的行數可能會很低,但你會快速通過鍵。 您應該進行一些計算,以了解如何通過INT 20億個密鑰進行日志記錄。 如果它不會在短時間內使用它們,請使用INT,否則將鍵大小加倍並使用BIGINT。

當您需要考慮導入/導出到多個數據庫時,請使用guid。 在處理多個子關系的數據集時,Guids通常比指定IDENTITY屬性的列更容易使用。 這是因為您可以在與數據庫斷開連接的狀態下在代碼中隨機生成guid,然后一次提交所有更改。 當guids正確生成時,它們很難偶然復制。 對於標識列,您通常必須在添加子數據之前對父行進行初始插入並查詢其新標識。 然后,在將它們提交到數據庫之前,必須使用新的父標識更新所有子記錄。 對孫子孫女來說同樣如此,等等。 它構建了許多看起來不必要和平凡的工作。 您可以通過在沒有IDENTITY規范的情況下使用隨機整數來執行與Guids類似的操作,但隨着時間的推移插入更多記錄時,碰撞的可能性會大大增加。 (Guid.NewGuid()類似於隨機的Int128 - 它還不存在)。

我使用Byte(TinyInt),Int16(SmallInt),Int32 / UInt16(Int),Int64 / UInt32(BigInt)用於不更改的小型查找列表或不在多個數據庫之間復制的數據。 (權限,應用程序配置,顏色名稱等)

我想無論你使用的是guid還是long,索引都需要與查詢一樣長。 表中通常還有其他字段的索引大於128位(例如用戶表中的用戶名)。 Guids和Integers之間的區別在於內存中索引的大小,以及填充和重建索引的時間。 大多數數據庫事務通常都在閱讀。 寫作很少。 首先要集中精力優化數據庫讀取,因為它們通常由未正確優化的聯接表,不正確的分頁或缺少索引組成。

與任何事情一樣,最好的辦法就是證明自己的觀點。 使用兩個表創建一個測試數據庫。 一個主鍵為long / long,另一個為guid。 每個用N-Million行填充。 在CRUD操作(創建,讀取,更新,刪除)期間監視每個的性能。 您可能會發現它確實有性能損失,但無關緊要。

服務器通常在沒有調試環境的盒子上運行,而其他應用程序占用硬盤的CPU,內存和I / O(特別是使用RAID)。 開發環境只能讓您了解性能。

暫無
暫無

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

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