為什麼對強實體同時使用通用標識符和單獨遞增的主鍵?
有一個很好的公開範例:ChEMBL(生物活性分子數據庫)的關係模型。這裡所有強實體(例如分子)都有一個數據庫範圍的唯一標識符,該標識符也可用作通用標識符:ChEMBL ID(例如ASPIRIN的 CHEMBL25)。這些強實體也有自己的增量 bigint 主鍵(例如 1280 表示同一個 Aspirin 實體)
該模型
chembl_id_lookup
擁有這兩個標識符,以及這些強實體的附加高級元數據。強實體關係也儲存這兩個標識符。然而,這不是有點多餘:
他們為什麼不直接使用 ChEMBL ID 的數字部分作為強實體主鍵。比如 CHEMBL25 可以轉化為 25 作為強實體主鍵?它仍然是獨一無二的。他們已經使用了 bigint,它肯定可以容納他們所有的實體。與提議的替代方案相比,他們的方法是否具有任何性能、完整性或清晰度優勢?
補充筆記:
他們最新的數據庫轉儲和模式圖可以從這裡下載。
更新 1
我問這個是因為我從頭開始為生物醫學研究開發關係數據模型,這比 ChEMBL 的範圍更廣。仍然 ChEMBL 足夠接近成為我的靈感之一。所以我不打算改變 ChEMBL 的架構。
我計劃將數據庫互動縮小到呼叫儲存過程。所以通用標識符–>代理bigint鍵轉換對使用者和應用程序將是透明的
更新 2
建議的替代方案不會改變整數用作代理主鍵的事實,但不是為每個表生成它們作為身份,而是為所有強實體生成一個全域唯一的整數序列。如果你把這個數字和你的前綴連接起來,那麼它將是通用標識符。
這種標識符的處理用於在國家生物資訊中心的 Enterez 平台中辨識基因。例如,基因CAN1具有
GeneID:856646
可供外部系統引用的通用標識符,其數字部分856646
是其數據庫中的唯一標識符 (UID)。但是我不知道那裡使用什麼樣的數據庫。
他們為什麼不直接使用 ChEMBL ID 的數字部分作為強實體主鍵。比如 CHEMBL25 可以轉化為 25 作為強實體主鍵?
但是,任何時候您想向使用者顯示該值,或將其發送到其他一些支持 ChEMBL 的應用程序時,您都必須重新添加前綴,並且任何時候讀取這樣的值從“其他地方”,你必須把它拆開,只得到數字部分。是的,這是可行的,但是每個轉換點都有可能有人“失去”一個並發送短值或加倍前綴。
然後是可怕的一天,他們決定更改為某種新的“標準”格式(強制性 XKCD 參考)。然後,您必須找到一種在截斷值和新值之間進行映射的方法,而不僅僅是更新外部可見的值,將舊值更新為新值。
bigint 代理鍵的最大優點是它的大小- 只有 8
$$ -ish $$每個表/索引中的字節,而不是每個 CHEMBL ID 的長度。 我建議使用完整標識符在數據庫“外部”使用,但使用內部(從未見過“外部”)、數字、代理鍵將記錄聯繫在一起。
單獨整數 ID 的重要原因是性能。
分組、排序連接使用的索引搜尋基於比較。整數在單個操作中進行比較,而基於字元的值在一個循環中逐個字元地進行比較。多字節字元集需要對每個字元進行多次迭代。假設 UTF8MB4 編碼中的兩個字元串,每 8 個字元長,平均需要 ~12 次比較,以確定哪個字元串在字典上位於另一個之前。
另一個原因是索引的磁碟佔用空間。CHAR(255) utf8mb4 的索引遠大於 BIGINT。
對於相對較小的數據庫而言,這一切都無關緊要,但使用專用整數 ID 而不是自然唯一的非整數候選鍵是一種常見模式。