我們?cè)谑褂肕ySQL的時(shí)候,主鍵的選擇上一般有兩種,那就是UUID和自增主鍵ID,使用這兩個(gè)做主鍵各自都有哪些優(yōu)缺點(diǎn)呢?為什么建議優(yōu)先使用自增主鍵ID呢? UUID(Universally Unique Identifier)全局唯一標(biāo)識(shí)符,是指在一臺(tái)機(jī)器上生成的數(shù)字,它的目標(biāo)是保證對(duì)在同一時(shí)空中的所有機(jī)器都是唯一的。 UUID 的生成是基于一定算法,通常使用的是隨機(jī)數(shù)生成器或者基于時(shí)間戳的方式,生成的 UUID 由 32 位 16 進(jìn)制數(shù)表示,共有 128 位(標(biāo)準(zhǔn)的UUID格式為:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12),共32個(gè)字符) 由于 UUID 是由 MAC 地址、時(shí)間戳、隨機(jī)數(shù)等信息生成的,因此 UUID 具有極高的唯一性,可以說(shuō)是幾乎不可能重復(fù),但是在實(shí)際實(shí)現(xiàn)過(guò)程中,UUID有多種實(shí)現(xiàn)版本,他們的唯一性指標(biāo)也不盡相同。 UUID在具體實(shí)現(xiàn)上,有多個(gè)版本,有基于時(shí)間的UUID V1,基于隨機(jī)數(shù)的 UUID V4等。 Java中的java.util.UUID生成的UUID是V3和V4兩種: Version 4 這種是最簡(jiǎn)單的(也是我們最常用的),只是基于隨機(jī)數(shù)生成的,但是也是最不靠譜的。適合數(shù)據(jù)量不是特別大的場(chǎng)景下。 Version 3是基于名稱空間的,所以在一定范圍內(nèi)是唯一的,而且如果有需要生成重復(fù)UUID的場(chǎng)景的話,這兩種是可以實(shí)現(xiàn)的。 很多人選擇UUID作為主鍵,其實(shí)也是有一定道理的,那就是UUID有幾何好處:
但是,如果只是因?yàn)檫@幾個(gè)好處就選擇UUID當(dāng)做主鍵ID的話,那么也不是很好的方案,因?yàn)樗娜秉c(diǎn)也比較明顯,如: 存儲(chǔ)空間比較大:UUID 通常以字符串形式存儲(chǔ),占用的存儲(chǔ)空間比較大。 不適合范圍查詢:因?yàn)椴皇亲栽龅模栽谧龇秶樵兊臅r(shí)候是不支持的。 不方便展示:主鍵ID有的時(shí)候會(huì)需要在系統(tǒng)間、或者前臺(tái)頁(yè)面展示,如果是UUID的話,就因?yàn)楸容^長(zhǎng)、并且沒(méi)有任何業(yè)務(wù)含義,所以不方便展示。 查詢效率低: 在UUID列上創(chuàng)建索引,因?yàn)樗荛L(zhǎng),所以索引的大小會(huì)變得非常大。大的索引會(huì)占用更多的磁盤(pán)空間,導(dǎo)致緩存命中率下降,進(jìn)而增加了磁盤(pán)I/O的需求。此外,大的索引還會(huì)導(dǎo)致查詢時(shí)的內(nèi)存開(kāi)銷(xiāo)增加。 當(dāng)使用UUID進(jìn)行排序時(shí),新的UUID值通常會(huì)插入到葉子節(jié)點(diǎn)的中間位置。這可能導(dǎo)致B+樹(shù)的頁(yè)分裂和平衡操作頻繁進(jìn)行,從而增加了寫(xiě)入的開(kāi)銷(xiāo)。每次分裂或平衡都涉及到數(shù)據(jù)的重新排序和移動(dòng),這會(huì)影響查詢的性能。 在 MySQL 中,可以通過(guò)設(shè)置 AUTO_INCREMENT 屬性實(shí)現(xiàn)ID的自增長(zhǎng),通??梢杂脕?lái)作為主鍵ID。 使用自增ID做主鍵的好處是:
但是,使用自增主鍵做主鍵ID也存在一定的問(wèn)題:
所以,在實(shí)際選型過(guò)程中,大家需要結(jié)合自己的實(shí)際業(yè)務(wù)做選擇。 簡(jiǎn)單的業(yè)務(wù)場(chǎng)景,數(shù)據(jù)量不大,增刪改查也不頻繁,可以選擇用UUID。 內(nèi)部系統(tǒng),數(shù)據(jù)量增刪改查頻繁,有頻繁的分頁(yè)查詢和展示等需求,優(yōu)先選擇自增主鍵ID。 對(duì)外系統(tǒng),數(shù)據(jù)量不大,也可以選用自增主鍵ID。 對(duì)外系統(tǒng),數(shù)據(jù)量大,分庫(kù)分表,則考慮使用雪花算法生成全局唯一ID。 |
|