Postgresql

對於已經具有保證唯一列的表,使用代理主鍵會產生什麼後果,無論是積極的還是消極的?

  • January 20, 2017

我最近製作了一張如下圖所示的表格

CREATE TABLE example(
 id SERIAL PRIMARY KEY,
 subindusty_id INT UNIQUE NOT NULL,
 name TEXT NOT NULL
 -- other fields...
)

我意識到在這個表中我可以刪除被呼叫的列id並創建subindustry_id主鍵。

回想起來,我能想到為什麼我沒有創建subindustry_id主鍵的唯一原因是為了保持一致性,考慮到我有很多其他的表都有一個名為id.

除了諸如一致性*之類的事情之外,當已經有另一個列可以作為一個好的主鍵時,將這個額外的 id 列作為主鍵是否有任何切實的好處/缺點?

*一致性,如“這就是其他表格的外觀”。你正在執行某種風格的那種。我想這個問題的重點是質疑給每個表一個id列的做法,不管他們可能已經有一個更合適的主鍵候選者。

我非常同意@MDCCL 的評論:

您應該分析每個特定情況——即,在其整個上下文中的每個特定表,即整個數據庫結構——來定義它是否需要附加系統生成的代理列,因為這樣的工件是一個額外的方面需要其特定的管理。從邏輯和物理的角度來看,與其他表格的外觀一致是無關緊要的

我身邊的一些建議(目前我想到的那些,可能還不是全部)

負面後果:

  1. 您需要更多空間來存放所有內容:每一行都更寬,並且您需要維護一個額外的索引。每次寫入都會花費(一點點)更多時間,每次讀取也會花費更多時間,因為您使用更多空間來讀取和寫入相同的真實資訊。假設您有幾個溫度計讀數的日誌,每秒一個。你有一張桌子thermometers (thermometer_id PK, ...etc...)和一張readings (thermometer_id, reading_timestamp, value_read)。您的讀數表有一個自然鍵: (thermometer_id, reading_timestamp),因為您不能同時有兩個不同的讀數。我通常會將此作為我的 PK,而忘記代理。
  2. 使用代理鍵往往會掩蓋數據的真實結構和含義。例如,假設您有一個表personsbooks並且books_liked_by_persons. 最後一個表是一個m x n表,大多數時候只包含(person_id, book_id)對。在這種情況下,添加三分之一id很可能毫無意義且嘈雜。

積極後果:

  1. 在某些非常特殊的情況下,您可能希望不同的表共享其結構的一部分(例如,您希望其中一些始終具有country_code, 和xxx_id),以便某些應用程序更容易開發,因為相同的模式可用於處理不同的表格。

$$ This tends to be rather uncommon, AFAIK, but is also possible. $$ 2. 使用代理鍵,即使有其他一些替代鍵也可以幫助您節省空間(可能還有時間)。想像一下你的自然密鑰是一個PGP 密鑰(注 1)。儲存它需要char(800)(大約)時間。想像一下,您有幾個表引用了這個表。它將節省(大量)空間以在原始表上具有代理整數鍵(8 或 16 字節),因為**引用表將儲存 8(或 16)字節而不是 800。需要完成記帳對於每個特定情況。 3. 如果您必須“手動”編輯您的數據(並且,有一天,您可能會這樣做),您不想尋找非常長的密鑰。在這種情況下,您更喜歡代理人。 4. 一些數據庫(至少現在不是 PostgreSQL)將使用您的主鍵作為集群索引來*集群您的表的數據(或者預設情況下可以這樣做,除非您明確聲明相反)。*在這種情況下,通常建議使用始終遞增的主鍵;以避免碎片化。

所以:每個案例都需要分析、權衡和決定。有時*,自動駕駛飛行可能會混淆一致性*。


旁注:有幾種不同的命名約定。我更喜歡id從不使用的那個,如果需要的話,一個persons表有一個person_id列。

注意 1:PGP 密鑰看起來或多或少類似於:

mQENBFiBGbcBCADBAe1p70ZPGwM6gmAAFTd13gv68rOUQEqlhddjkJZoiKs8SJuX m4Hpu29+4msQ91071R2yGZ+iydO2laRqWD1jFmF1qOTWiwYkrxYc288/XLbGi7NY gz9CPKlaH8N4VJBPC6eoRJgpUawBygERf+YFxBEXipWrZbusFrnHCilGGuOwIDAc UmYf7XNFZrg4+i+QEkBqWnBtd4Q7tkdTTywFDMZ3H+fwrDp+8M3zUwi10PCxJbQd JkKzXDFemaOHiDxWKNRg7CFyCBRq5K6mfXZuPeAtVOxFMFRnvyJ75HWv4Ss5n40b tpL/kmSQ9cHgl0nWHS+LMF55zZsAKToNaW6FABEBAAG0FXNvbWV0aGluZ0Bub3do ZXJlLmNvbYkBHAQQAQIABgUCWIEZtwAKCRDigzJ94dxj1hujCACFt22wZD5yn5/J 3cGLonszqgDRMNzmkdlJjiZi+2fC51z2mkQcy3rlzrQX9K1Mu3TLxPfwyMMiZkut trleZI4KyAD1hQRm4hQ4f+xx++xOqnMh5c7KsE6AwnGxeDgLy8hD3IJCmrDFwZ93 4XgZ+iXEzFxMcwmLeJ7xg7re4NTlovpIj1QetXqfEHydHQ1AJCqBjGSs805DBHGO nKAwBXuPI67Kcry+HIhn4ZaIXmXLGvXStJAz2bX8o/nQaVoC/YOyUTMZadR3jtdf ka5OeyvudCiKTNL3I1oDbhFFfGEhF2w66wp8acJ4z5bYkaQ5RFpEMI1ISfSn7Ypg FZln1sTo =RYbd

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