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

浙公網(wǎng)安備 33010602011771號