目錄
1. 主鍵定義... 5
2. 主鍵設計原則... 5
2.1 確保主鍵的無意義性... 5
2.2 采用整型主鍵... 5
2.3 減少主鍵的變動... 5
2.4 避免重復使用主鍵... 6
2.5 主鍵字段定義區分... 6
3. 主鍵方案... 6
3.1 自增ID.. 6
3.2 UUID.. 7
3.3 ID物理主鍵+UUID邏輯主鍵... 7
4. 總結... 8
1. 主鍵定義
表中經常有一個列或多列的組合,其值能唯一地標識表中的每一行。這樣的一列或多列稱為表的主鍵,通過它可強制表的實體完整性。
2. 主鍵設計原則
總原則:根據數據庫表的具體使用范圍來決定采用不同的表主鍵定義。
2.1 確保主鍵的無意義性
在開發過程中,有意義的字段例如“用戶登錄信息表”將“登錄名”(英文名)作為主鍵,“訂單表”中將“訂單編號”作為主鍵,如此設計主鍵一般都是沒什么問題,因為將這些主鍵基本不具有“意義更改”的可能性。
但是,也有一些例外的情況,例如“訂單表”需要支持需求“訂單可以作廢,並重新生成訂單,而且訂單號要保持原訂單號一致”,那將“訂單編號”作為主鍵就滿足不了要求了。
因此在使用具有實際意義的字段作為主鍵時,需要考慮是否存在這種可能性。
要用代理主鍵,不要使用業務主鍵。任何一張表,強烈建議不要使用有業務含義的字段充當主鍵。我們通常都是在表中單獨添加一個整型的編號充當主鍵字段。
2.2 采用整型主鍵
主鍵通常都是整數,不建議使用字符串當主鍵。(如果主鍵是用於集群式服務,可以采用字符串類型)
2.3 減少主鍵的變動
主鍵的值通常都不允許修改,除非本記錄被刪除。
2.4 避免重復使用主鍵
主鍵的值通常不重用,意味着記錄被刪除后,該主鍵值不再使用。
2.5 主鍵字段定義區分
主鍵不要直接定義成【id】,而要加上前綴,定義成【表名id】或者【表名_id】
3. 主鍵方案
3.1 自增ID
優點:
n 數據庫自動編號,速度快,而且是增量增長,聚集型主鍵按順序存放,對於檢索非常有利。
n 數字型,占用空間小,易排序,在程序中傳遞方便。
缺點:
n 當系統與其他系統集成時,需要數據導入時,很難保證原系統的ID不發生主鍵沖突。在多個數據庫間進行數據的復制時(SQL Server的數據分發、訂閱機制允許我們進行庫間的數據復制操作),自動增長式字段可能造成數據合並時的主鍵沖突及表關聯關系的丟失。
n 如果其他系統主鍵不是數字型,會導致修改主鍵數據類型,導致其他相關表的修改。
n 在數據緩沖模式下,很難預先填寫主鍵與外鍵的值。
n 自增量的值都是需要在系統中維護一個全局的數據值,每次插入數據時即對此次值進行增量取值。當在產生唯一標識的並發環境中,每次的增量取值都必須為此全局值加鎖解鎖以保證增量的唯一性。造成並發瓶頸,降低查詢性能。每創建一條記錄都需要對表加一次鎖,在高並發環境下開銷較大。
3.2 UUID
UUID是指在一台機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的。在UUID的算法中,可能會用到諸如網卡MAC地址,IP,主機名,進程ID等信息以保證其獨立性。
優點:
n 全局唯一性、安全性、可移植性。
n 能夠保證獨立性,程序可以在不同的數據庫間遷移,效果不受影響。
n 保證生成的ID不僅是表獨立的,而且是庫獨立的,在你切分數據庫的時候尤為重要。
缺點:
n InnoDB為聚集主鍵類型的引擎,數據會按照主鍵進行排序,由於UUID的無序性,InnoDB會產生巨大的IO壓力。InnoDB主鍵索引和數據存儲位置相關(簇類索引),uuid 主鍵可能會引起數據位置頻繁變動,嚴重影響性能。
n 作為主鍵,UUID長度過長,主鍵索引KeyLength長度過大,而影響能夠基於內存的索引記錄數量,進而影響基於內存的索引命中率,而基於硬盤進行索引查詢性能很差。嚴重影響數據庫服務器整體的性能表現。
3.3 ID物理主鍵+UUID邏輯主鍵
InnoDB不適合使用UUID做物理主鍵,可以把它作為邏輯主鍵,物理主鍵依然使用自增ID。
主鍵仍然用auto_increment_int來做,而另加一個uuid做唯一索引,表外鍵關聯什么的,還 用uuid來做,也就是說auto_increment_int只是一個形式上的主鍵,而uuid才是事實上的主鍵,這樣,一方面int主鍵不會浪費太多空間,另一方面,還可以繼續使用uuid。
優點:
n InnoDB會對主鍵進行物理排序,這對auto_increment_int類型有好處,因為后一次插入的主鍵位置總是在最后。但是對uuid來說則有缺點,因為uuid是雜亂無章的,每次插入的主鍵位置是不確定的,可能在開頭,也可能在中間,在進行主鍵物理排序的時候,勢必會造成大量的 IO操作影響效率。
缺點:
n 同自增ID的缺點:全局值加鎖解鎖以保證增量的唯一性帶來的性能問題。
4. 總結
本文主要針對MySQL數據庫中的InnoDB存儲引擎的主鍵設計原則進行調研,挑選了幾種主流的主鍵方案進行優缺點的分析和對比,並最終建議選擇自增ID作為物理主鍵,同時使用UUID作為邏輯主鍵的方案。
如果一些特殊的表,比如說日志表,其不需要維護,可以采用數據庫自動增長ID的方式。這種方式性能好,產生也很方便。但是維護很麻煩。
