Sql-Server

當我可以使用其他欄位作為關鍵欄位時,我為什麼要創建一個 ID 列?

  • August 9, 2015

可能重複:

為什麼使用 int 作為查找表的主鍵?

到目前為止,我習慣於為每個表創建一個 ID 列,並且它很實用,它讓我不必考慮關於主鍵理論的決策。

我大學的教授建議全班從一個或多個欄位中創建主鍵,這些欄位構成關於每一列的一個唯一資訊。是的,我想養成使用自然鍵而不是代理鍵的習慣。維基百科上列出了代理鍵的優缺點,我強烈推薦這篇文章

我見過人們對所有內容都使用整數 ID 欄位,但沒有人評判這種方法,因為

  • 它“看起來”高效
  • 使用了一個數字欄位,它看起來更酷,因為它在記憶體中每行的大小

我開始認為一個額外的 ID 欄位只是創建了沒有實際好處的冗餘數據。那麼當我可以使用其他列作為關鍵欄位時,為什麼還要創建一個 ID 列呢?

  • 如果您的 ID 欄位是 32 位,則它已經相當於 4 個 ASCII 字元。
  • 如果您的 Id 欄位是64 位整數,它是8個字元串,因此它實際上並沒有節省那麼多記憶體(這裡暗示的是比較中使用的記憶體。額外的 id 列已經添加到使用的記憶體中(HDD 和 RAM ) )
  • 額外的 ID 欄位會使您的索引成本加倍,因為您還將索引一個可用作主鍵的唯一欄位。
  • 如果您需要可以用作關鍵欄位的數據,您可以進行額外的連接,例如,如果您在一篇部落格文章中儲存了唯一的使用者 ID,以顯示作者的姓名,您可以進行連接查詢,如果您的密鑰欄位是作者的名字,你不需要加入,因為你將相關數據儲存在部落格文章表中。具有有意義數據的外鍵欄位減少了對子查詢或連接的需求

在此處輸入圖像描述

  • 創建一個額外的 id 欄位“添加”到記憶體負載,它不是唯一字元串欄位的替換,您不是用整數替換 char-varchar 欄位,而是添加一個額外的列,它會創建額外的數據流。所以數據儲存的任何比較都應該在“string”和“int+string”之間進行。添加整數 id 欄位不會節省空間。

另一方面

  • 分配從使用者輸入中獲取價值的主鍵數據可能會出現問題,因為人們可能會輸入錯誤的社會安全號碼,並且由於獨特的政策,想要註冊的實際人將無法註冊。這可以通過在原始號碼中添加一個或多個額外的數字來規避。

額外資源:

  1. Natural vc 代理鍵的比較

我從閱讀文章中得出的結論是,我應該盡可能使用自然鍵**,**而不是跳過考慮自然鍵並每次都使用代理鍵,就好像它是一個標準一樣。

1 -它更快。 整數上的A比字元串欄位或欄位組合上的 aJOIN快得多。JOIN比較整數比比較字元串更有效。

2 -它更簡單。 基於單個數字欄位映射關係比基於不同數據類型的其他欄位的組合要容易得多。

3 -它與數據無關。 如果您匹配,則ID無需擔心關係發生變化。如果你匹配一個名字,如果他們的名字改變了(比如結婚),你會怎麼做?如果你匹配一個地址,如果有人搬家怎麼辦?

4 -更高效 如果您在(自動遞增的)int 欄位上進行集群,您可以減少碎片並減少數據集的整體大小。這也簡化了覆蓋您的關係所需的索引。

編輯

對於您剛剛添加的具體要點:

1 和 2 - 比較一個 int 比比較一個字元串要快得多,除了空間考慮。您還可以方便地忽略儲存可變長度欄位長度所需的成本(通常每行每個欄位 2 個字節)。

3 - 如果你聚集在ID球場上,那麼它不會增加任何額外的東西。它節省了空間,因為您使用的是更有效的行 ID。

4 - 然後當那個人更改他們的使用者名時,您的連結都會中斷。

5 - 你真的不知道你在說什麼。JOIN您確實必須儲存數據,這是正確的,但是索引和int 比在其他欄位的組合上更有效。

因為人們從經驗中了解到,使用這些欄位會導致問題。

我已經開發數據庫應用程序 20 年了。最關鍵的是,我花了五年時間研究數據倉庫。在早期,選擇另一個領域似乎沒問題。然後我們發現重複的記錄,有時缺少唯一的驗證,有時(經常)使用者提供了現在需要合併的不同資訊,或者其他什麼,合併和管理記錄是一場噩夢。

即使(甚至特別是!)標識符“似乎”是唯一的,這也可能不是真的。例如:美國社會安全號碼。它應該是一個人獨有的,對吧?當然可以,但是如果某些記錄輸入了過去被使用者錯誤輸入的 SSN,該怎麼辦?現在,為新記錄輸入的新有效數字可能會出現衝突問題。附帶說明的是,主鍵也不應該顯示,因為它們會導致使用者對它們進行假設,並且它們也不利於網站 URL 的最佳安全模型。

始終考慮 - 使用者是否會將此 URL 加入書籤並期望它在未來工作?

所以人們學會了:

**當代理具有“任何”商業價值或意義時,不要使用“代理鍵”(例如 SSN)作為主鍵。

相反,請使用唯一且不是從應用程序數據派生的主鍵。**

引用自:https://dba.stackexchange.com/questions/8334