2012-03-29 82 views
3

我們有一個CreateDateTime PK表。插入程序是多線程的。顯然,這不是線程安全的。有一個3列組合鍵,可以從表中的現有數據製作。這是一個日誌表,流量預計很高。性能是主要關注的問題。主鍵選擇的性能

我們的開發人員之一認爲,由於SQL內部存儲datetime(Epoch?)的方式,DateTime是出於性能原因的最佳PK。

我建議我們在3列中創建一個組合鍵。這個關鍵是否會對性能產生負面影響?

也有人建議我們使用GUID PK's。性能再次出現問題。

是否最好切換到組合鍵?如果是,我們如何解決/解釋這些性能問題?

+1

'datetime'可能因爲分辨率問題而不安全(這聽起來很可能兩個線程會同時登錄)。具有強制性PK索引的複合鍵幾乎肯定會增加RDBMS引擎的負載。我會用GUID去,因爲它速度快,可靠,並且有足夠的分辨率。 – dasblinkenlight 2012-03-29 13:22:56

+0

我想你應該閱讀一些關於爲sql server選擇主鍵的文章。通過「pinaldave」查看本文。 候選鍵和主鍵之間的區別 http://blog.sqlauthority.com/2009/10/22/sql-server-difference-between-candidate-keys-and-primary-key -2/ – 2012-03-29 13:26:38

+0

'表現是主要的關注點'?你的意思是讀取性能,寫入性能,併發處理寫入性能等,等等? – MatBailie 2012-03-29 13:42:09

回答

4

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相同的問題 - 只是稍微突出一點。

然後還有一個需要考慮的問題:表上的聚簇鍵將被添加到表上每個非聚簇索引中的每個條目上 - 因此,您確實希望確保它小到可能。通常情況下,具有超過250億行的INT應該足以滿足絕大多數表的要求 - 並且與GUID作爲集羣密鑰相比,您可以爲磁盤和服務器內存節省數百兆的存儲空間。

快速計算 - 使用INT與GUID作爲主要和聚集關鍵字:

  • 基本表與1'000'000行(3.8 MB與15.26 MB)
  • 6個的非聚集索引(22.89 MB與91.55 MB)

合計:25 MB vs. 106 MB - 這只是一張桌子!

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

至於組合鍵:在我看來,主要缺點是,希望所有表到現在引用此複合PK必須具有複合FK,其中全部爲組合PK中定義的列。當你有很多需要使用這個組合鍵將子表連接到一個表的查詢時,這會變得非常不方便。

DATEITME對於主鍵似乎不是一個好主意 - 在SQL Server中,DATETIME的準確度爲3.33ms,因此在繁忙的系統中很可能會有非唯一值 - 對於PK來說不是個好主意!

如果性能是您的最高優先級,那麼我肯定會推薦一個INT IDENTITY列(即使它是代理列)用於您的唯一聚集主鍵索引。

+2

非常好的思想答案 – HLGEM 2012-03-29 13:40:21