[英]Could using Sequential Guid as primary key in SQL Server lead to low performance for big data?
我遇到過的最大的數據庫是SQL Server數據庫,其中一個表包含200,000行。 我使用Guid
作為該數據庫中的主鍵,而不是順序guid。 在其中有大約30個並發用戶的系統中,我沒有遇到任何性能問題。
最近,我設計並開發了一個企業應用程序開發框架。 為了利用“工作單元”模式的優勢,我使用了順序的guid作為主鍵,以便對記錄進行物理排序。 由於我在大型數據庫方面的經驗僅限於我剛剛提到的內容,因此我是否會嚴重擔心是否要使用此框架為擁有1000個並發用戶的大型組織開發企業應用程序,這將保留數百萬條記錄使用順序guid作為主鍵的數據會導致性能問題嗎?
如果是,到什么程度? 然后如果是,那么是否可以通過改進數據庫服務器硬件(處理器和RAM)來解決,然后再提高到什么程度?
預先感謝您分享您的經驗和知識
GUID
似乎是您的主鍵的自然選擇-如果確實需要,您可能會爭辯說將其用於表的主鍵。 我強烈建議您不要使用GUID
列作為群集鍵 ,默認情況下,SQL Server 會這樣做 ,除非您明確要求不要這樣做 。
您確實需要將兩個問題分開:
主鍵是一種邏輯結構-候選鍵之一,可唯一且可靠地標識表中的每一行。 實際上,可以是任何東西INT
, GUID
或字符串-選擇最適合您的方案的東西。
集群鍵 (在表上定義“集群索引”的一列或多列)-這是與物理存儲相關的事情,在這里,小型,穩定,不斷增長的數據類型是您的最佳選擇INT
或BIGINT
作為默認選項。
默認情況下,SQL Server表上的主鍵也用作群集鍵-但這不是必須的! 當打破了以前的基於GUID的主/集束鍵分成兩個獨立的按鍵我親自看到巨大的性能提升-在主(邏輯)鍵GUID
,並在一個單獨的集群(排序)鍵INT IDENTITY(1,1)
欄。
正如索引王后 金伯利·特里普 ( Kimberly Tripp)和其他人多次指出的那樣,由於聚類鍵的GUID
並不是最優的,因為它的隨機性,它將導致大量的頁面和索引碎片,並且通常會導致性能下降。
是的,我知道– SQL Server 2005及更高版本中有newsequentialid()
,但即使它不是真正且完全順序的,因此也遭受了與GUID
相同的問題-不太明顯。
然后還有另一個要考慮的問題:表上的集群鍵也將添加到表上每個非集群索引的每個條目中,因此,您真的要確保它盡可能小。 通常,具有2+十億行的INT
應該足以容納絕大多數表-與GUID
作為集群鍵相比,您可以為磁盤和服務器內存節省數百兆的存儲空間。
快速計算-使用INT
vs. GUID
作為主鍵和聚類鍵:
總計:25 MB和106 MB-那就在一張桌子上!
是的-較大的表或索引大小自動意味着需要從磁盤加載,保存在內存中,再傳輸到客戶端的更多數據頁-所有這些都對性能產生負面影響。 到底有多少影響實際上取決於數據庫設計和數據分布的許多因素,因此任何廣義的預測幾乎都是不可能的...
再想一想-金伯利·特里普(Kimberly Tripp)的優秀著作-讀它,再讀一次,消化它! 確實,這是SQL Server索引的福音。
在以下情況下出現順序GUID與“常規” GUID的問題:
對於聚集索引,SQL Server“按順序”將新記錄添加到表中。 因此,較大的值位於表的“末尾”,在這種情況下,位於最后一個數據頁上。 這對於標識列很方便,因為可以保證它們大於任何先前的值。 根據定義,最后一個數據頁沒有碎片。
GUID沒有此屬性。 它們最終被“插入中間”,從而導致碎片。
為什么您不認為這是一個問題? 可能有多種原因:
至於后一點,如果記錄足夠小,那么每頁上可能會出現上千條記錄。 擁有200頁的數據,碎片可能不是一個大問題。
擁有30個並發用戶,您可能根本沒有交易重疊。 如果每個用戶每分鍾修改一次數據庫,那么您將有2秒的時間來完成事務-通常足夠的時間。
不過,我建議使用順序的GUID或標識列。 這樣可以使數據庫更清潔。 但是,定期對數據庫進行碎片整理是另一個可行的選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.