關於自增主鍵和UUID的比較,能夠從數據插入前,插入中,插入三個階段進行比較,他們有各自的有點,固然也有各自的不足。下面就分三個階段說說優缺點。mysql
1)UUID 須要手動維護,要求是保證每次生成的數據都是不一致的,而後咱們須要手寫sql插入,若是代碼邏輯中含有大量這種非業務相關的代碼,實際上是很不友好的,因此儘可能透明。可是在代碼中(Java)你能夠在未插入以前就知道了主鍵ID,這個在有關聯表須要插入時很是不錯。sql
2)自增主鍵 插入前無需維護,編寫的sql也不用管這個字段,數據庫本身維護,對寫程序來講徹底透明。缺點就是插入前代碼中(Java)並不知道主鍵。數據庫
1)UUID 長度相對比較大,若是大批量數據插入,在網絡傳輸間,實際上這個字段佔用的空間是不容小覷的,固然通常的程序不會擔憂這個,由於選用 Hibernate 的人,基本不會在意某個字段的事。另外,既然是主鍵那麼必然要考慮主鍵的惟一性,如何作這個惟一的校驗呢?尤爲是併發狀況下,若是有多個相同的鍵同時插入怎麼辦?因此我以爲這裏會有個鎖(多是鎖索引,也多是鎖表),所以使用UUID併發插入確定會發生阻塞的。這個能夠去試驗一下,開兩個事務,使用相同的ID插入,後一個插入確定會被阻塞,因此我以爲這裏確定有一個判斷是否已經存在鍵的代碼,並且是同步的,若是鍵存在那麼阻塞後面的操做,固然初步判斷不是鎖表,若是是鎖表會致使全部的插入阻塞,實際上不會。網絡
2)自增主鍵 在插入時徹底沒有流量,由於都是數據庫自己維護,因此很乾淨。關於自增主鍵插入有很併發
多須要補充的知識,這裏先從MySQL之前的版本提及,之前採用的是:對每一個含有自增加值的表都有一個自增加計數器(auto-increment counter),當有數據插入時就會執行操做:spa
select max(auto_inc_col) from t for update;線程
這個之前自增加字段鎖的方式 AUTO-INC Locking,稱爲傳統模式,他還有個很突出的特色是自增主鍵的值不用等待事務提交才生成,而是馬上生效,因此必定程度上提升了併發效率。可是,對於併發插入或者 insert..select 這種大批量數據插入的方式都是會被阻塞的。索引
而後就出現了新的自增加鎖方式,版本> MySQL 5.1.22開始,InnoDB提供了一種輕量級互斥的自增加實現機制,在內存中會有一個互斥量(mutex),每次分配自增加ID時,就經過估算插入的數量(前提是必須可以估算到插入的數量,不然仍是使用傳統模式),而後更新mutex,下一個線程過來時重新 mutex 開始繼續計算,這樣就能避免傳統模式非要等待每一個都插入以後才能獲取下一個。這種實現方式是經過 innodb_autoinc_lock_mode 的來來肯定鎖的方式。事務
我如今使用的 MySQL版本是 5.6.16 引擎是 innodb.內存
首先執行以下語句,檢查數據庫自增主鍵鎖的模式(> MySQL 5.1.22 )
SHOW VARIABLES LIKE 'innodb_autoinc_lock_mode' 默認是 1
innodb_autoinc_lock_mode 有三個值分別是
0(traditional) ,這個就是以前說的 AUTO-INC Locking,併發相對較差
1(default consecutive),對不一樣的插入操做會有不一樣的方式,即傳統方式、互斥方式
2(interleaved),徹底使用互斥方式,併發最好,可是缺點明顯,大併發下可能會出現重複。
咱們只用考慮 innodb_autoinc_lock_mode = 1 的狀況,另外兩種是固定的模式,而連續模式究竟是使用傳統仍是使用交叉模式,就是根據插入數據的量是否可估算的,先看看插入的分類:
Simple inserts
經過分析insert語句能夠肯定插入數量的insert語句,
Bulk inserts
經過分析insert語句不能肯定插入數量的insert語句
Mixed-mode inserts
不肯定是否須要分配 auto_increment id
名稱 | 插入語法 |
Insert-like | INSERT,INSERT … SELECT, REPLACE, REPLACE … SELECT, LOAD DATA, INSERT VALUES(),VALUES() |
Simple inserts | INSERT, INSERT … VALUES(),VALUES() |
Bulk inserts | INSERT … SELECT, REPLACE … SELECT, LOAD DATA |
Mixed-mode inserts | INSERT INTO t1 (c1,c2) VALUES (1,’a'), (NULL,’b'); INSERT … ON DUPLICATE KEY UPDATE |
總結:若是是連續模式,那麼對 Simple inserts 採用的是互斥方式,若是是 Bulk inserts 採用的是傳統模式,Mixed-mode inserts 模式其實也是使用互斥方式,可是缺點就是浪費大量的ID。
回到問題上,mysql 對自增主鍵作了不少特殊處理,因此在插入的併發狀況下仍是能夠接受的,固然相對UUID仍是差了點,畢竟只要UUID只要維護惟一性,然而自增主鍵首先要考慮生成規則,而後還要考慮惟一性,然而就是這個生成規則MySQL已經採用互斥方式進行了改進。
1)UUID 仍是長度的問題,這個影響的不只僅是磁盤空間問題,更多仍是索引的建立與查找,MySQL採用的 BTree+ 索引,並且主鍵都會附帶在全部其餘的索引的第一列(默認),首先致使索引空間變大,其次還會致使節點的分裂和移動,因此插入的時候由於須要維護索引更新,因此插入相對比較慢。另外UUID有一個很大的好處就是數據庫合併,由於任何UUID都是不一致的,因此當作庫-表合併時,不會出現主鍵衝突,這是自增主鍵作不到的。
2)自增主鍵 的長度相對較小,並且自增主鍵只能是數字,因此索引更快,磁盤空間更小,在數據插入時雖然會致使節點的分裂可是不會移動。
使用 insert t values(),() 比使用批處理使用 insert t values();insert t values(); 要快上好幾倍,因此創建使用第一種方式,固然若是你可使用 insert t select ,那是最好不過了。在使用第一種方式也有注意的地方,若是values 裏面已經有主鍵的值了,那麼使用併發操做會發生鎖超時,緣由應該是在數據惟一性檢查那裏作了同步,若是沒有主鍵的值,那麼併發是最快的,由於它採用互斥增加方式生成主鍵ID。
《mysql 技術內幕》