推薦文章:
http://tech.ddvip.com/2008-10/122517676785777_4.html
使用GUID作為數據庫主鍵的測試
http://www.cnblogs.com/chiname/articles/227584.html
使用uniqueidentifier還是IDENTITY生成主鍵?
問題
我正在設計一張表,并且決定創建一個自動生成主鍵值而不是創建自己的模式或者使用自然鍵。我知道SQL Server提供了全球唯一識別碼(GUID),也提供了創建這些值的標識符。請問這些方法有哪些優缺點呢?
專家解答
確實,你可以通過很多種方法來為你的表自動生成主鍵值。最常見的一種方法是通過使用IDENTITY字段屬性,或者指定帶有默認NEWID() 或NEWSEQUENTIALID()函數的唯一識別碼數據類型。此外,在SQL Server復制中,全球唯一識別碼經常被用在帶有更新訂閱的合并復制或者事務復制的唯一識別符行中。
NEWID()和NEWSEQUENTIALID()有什么區別呢? NEWID()隨機生成一個基于服務器網卡的標識符號碼和CPU塊唯一號碼的保證的唯一值。與此相反,NEWSEQUENTIALID()按照順序生成這些值而不是隨機生成。
正如你看到的,第一張表使用NEWID()生成隨機值而第二張表使用NEWSEQUENTIALID()生成有順序的值。由于沒有通過IDENTITY方法生成整數,生成的全球唯一識別碼值看起來在工作中不易于使用。這是另一個要注意的地方。SQL Server在內存中保存最后一個生成的標識值,這樣可以在通過使用SCOPE_IDENTITY(),@@IDENTITY或者CHECK_IDENT(取決于你要求的范圍)的INSERT語句之后,重新找到這個標識值。這與獲得最后一個全球唯一標識符值沒有任何相似之處。如果你使用一個全球唯一標識符,你必須創建自己的機制來獲得最后一個插入值(比如,在插入之前重新找到全球唯一標識符或者使用SQL Server 2005 OUTPUT從句)。
存儲效果
根據輸出結果,你可以看到NEWID()測試表是成碎片的,因為它的碎片比例是98%。此外,你可以看到這些行分散在490頁中。這是因為生成主鍵的隨機屬性導致了頁拆分。與此相反,IDENTITY 和NEWSEQUENTIALID()測試表只有極小的碎片比例,這是因為它們按照特定順序自動生成鍵。結果使它們免受頁拆分之苦,而使用NEWID()方法具有頁拆分的困擾。盡管你可以用磁盤碎片整理程序處理NEWID()表,但是主鍵產生的隨機屬性仍然會由于將來對表做插入操作而引起頁拆分和碎片。盡管如此,頁拆分仍然可以通過指定恰當的FILL FACTOR而減到最小。
現在也來考慮這個問題,因為唯一標識符數據類型消耗16字節的數據,任何在一張表中使用一個全球唯一識別碼作為聚集索引的定義非聚集索引大小都會受到影響,因為這些非聚集索引的葉級別包含作為指示器的聚集索引鍵。因此,如果一個IDENTITY被定義為整數或者bigint數據類型,那么任何非聚集索引的大小可能會因為比較大而終止。
很明顯,使用IDENTITY來自動生成鍵值比使用全球唯一標識符方法更具有優勢:
l IDENTITY生成值是可以配置的,并且易于閱讀,易于在工作中使用。
l 可以使用更少的數據庫頁來滿足查詢請求。
l 與NEWID()方法相比,它在頁拆分(與前面相關)方面的擔憂可以消除。
l 數據庫規模最小化。
l 存在系統函數來獲得最后生成的IDENTITY值(比如SCOPE_IDENTITY()等)
一些系統函數,比如MIN()和MAX(),不能在唯一標識符字段中使用。
使用GUID作為數據庫主鍵的測試
可以看出在以GUID作為主鍵的表中加一個時間類型或是Int類型的索引可以彌補以GUID作為主鍵帶來的性能損失。
3、這樣做是為了模擬現實使用情況,當然這樣很片面,因為在平時使用過程中,經常用到分頁,計算數據總數,目的是看看在如果在表中不另外加索引會不會影響計算效率,看來用GUID作為主鍵必須要另外加索引才能保證入count這樣的計算不至于消耗太多時間,但是用int類型好像就不會消耗太多時間的,所以這樣一比較就看出,如果用varchar字段類型做主鍵的表,表內一定需要個非聚集索引。
posted on 2010-04-20 11:52
黃小二 閱讀(1508)
評論(0) 編輯 收藏 所屬分類:
[DB]