mysql 主鍵選擇

轉載:http://www.cnblogs.com/chutianyao/archive/2012/11/04/2753995.html
(針對InnoDB引擎)我們實際生產環境可能會使用四類屬性作爲主鍵:

(1). 自增序列;

(2). UUID()函數生成的隨機值;

(3). 用戶註冊的唯一性帳號名稱,字符串類型,一般長度爲:40個字符;

(4). 基於一套機制生成類似自增的值,比如序列生成器;

那麼我們接下來,再分析下這四類屬性各自作爲表主鍵的優缺點:

(1). 自增序列:從小到大 或從大到小的順序模式增加新值;數據類型也利於進行主鍵值比較;存儲空間佔用也相對最小,一般設置爲:4個字節的INT類型或 8個字節的BIGINT類型;若是想進行數據水平拆分的話,也可以藉助設置mysqld實例的2個參數:auto_increment_increment 和 auto_increment_offset;另外,唯一缺點就是自增序列是一個表級別的全局鎖,在5.0系列大規模併發寫的時候,因鎖釋放機制的問題容易出現瓶頸,但是5.1系列做了改進,基本上不存在此問題;

(2). UUID()函數:值爲隨機性+固定部分,其值產生是無序的,且同一臺服務器上產生的值相同部分爲77.8%;產生的值字符個數爲36,按utf8編碼計算,佔用的存儲空間爲36個字節;對於數據水平拆分支持,無需特殊設置;

(3). 使用用戶註冊的帳號名稱,字符串類型,其值的產生依賴用戶輸入,爲此數據基本上爲無序增加,字符串的長度也是不定的,只能通過前段技術控制最短最大長度值的限制,對水平拆分支持,無需做特殊設置;

(4). 序列生成器的架構,類似自增序列,不過需要藉助額外的開發工作量,以及提供一個第三方的服務,可以規避自增序列的字增全局鎖的問題,提高併發,對數據水平拆分可以更好地支持;

(5). 雙主複製架構的概率性碰到的場景:主服務器的數據執行成功,而沒有複製到在線備用服務器時,出問題的概率確實存在,其他類型的做法,也必須人工干涉解決,都無簡單且合理的自動化辦法,以上四種辦法都無法規避;

通過四種屬性值作爲主鍵的優缺點分析,以及對比前面我們闡述的主鍵需要的優秀素質,若是不考慮水平拆分的問題,帶來額外設置上的麻煩,則自增序列是最佳的主鍵字段選擇;用戶的註冊帳號本身要求唯一性且非空的場景下,則可以作爲主鍵字段的選擇;若是考慮水平拆分的問題,則採用自增序列生成器的架構,非常易用和可靠的實現方式,產生的值是最佳主鍵字段的選擇;

MySQL UUID函數的詳解

http://www.mysqlops.com/2011/03/01/mysql-uuid.html

MySQL中可以有二類用於生成唯一值性質的工具:UUID()函數和自增序列,那麼二者有何區別呢?我們就此對比下各自的特性及異同點:

l 都可以實現生成唯一值的功能;

l UUID是可以生成時間、空間上都獨一無二的值;自增序列只能生成基於表內的唯

一值,且需要搭配使其爲唯一的主鍵或唯一索引;

l 實現方式不一樣,UUID是隨機+規則組合而成的,而自增序列是控制一個值逐步增長的;

l UUID產生的是字符串類型值,固定長度爲:36個字符,而自增序列產生的是整數類型值,長度由字段定義屬性決定;

接下來,詳細講解下UUID()函數產生的值:

oot@localhost : (none) 06:09:40> SELECT UUID(),UUID(),LENGTH(UUID()),CHAR_LENGTH(UUID())\G

***************** 1. row *****************

UUID(): de7ee638-4322-11e0-85ab-842b2b4a7e75

UUID(): de7ee642-4322-11e0-85ab-842b2b4a7e75

LENGTH(UUID()): 36

CHAR_LENGTH(UUID()): 36

1 row in set (0.00 sec)

從上面的執行結果部分的信息看:

l 同一個SQL語句中,多處調用UUID()函數得到的值不相同;

l 得到的隨機值由5個部分組成,且分隔符位爲:中劃線;

l 多次調用或執行得到的後2組值相同,若把mysqld服務器關閉,重新啓動之後,會發現第四組的組與未重啓前的值發生變化,然後一直不變化,只要重新啓動mysqld服務就會發生變化。另外,對於同一臺機器,第五組值始終不會發生變化;

l 字符個數爲:36,佔字節數爲:36(注:系統默認字符集編碼:utf8);

針對UUID產生的值組成部分,作如下解說:

l 前三組值是時間戳換算過來的;

l 第四組值是暫時性保持時間戳的唯一性。例如,使用夏令時;

l 第五組值是一個IEE 802的節點標識值,它是空間上唯一的。若後者不可用,則用一個隨機數字替換。假如主機沒有網卡,或者我們不知道如何在某系統下獲得機器地址,則空間唯一性就不能得到保證,即使這楊,出現重複值的機率還是非常小的。

UUID函數對複製的支持:

UUID函數屬於不確定性函數,爲此不支持MySQL 複製的STATEMENT模式,但是支持MIXED、ROW二種模式,大家可以設置2組測試模式,以5.1.系列版本爲例。

測試基於命令行模式複製:

tx_isolation = REPEATABLE-READ

binlog_format = STATEMENT

測試基於命令行/混合模式複製:

tx_isolation = REPEATABLE-READ

binlog_format = MIXED OR ROW

在主服務器上執行同一個SQL語句:

INSERT INTO test_uuid(username) VALUES(UUID());

然後再比對主從服務器上表中存儲的值,會發現基於命令行模式的:主從不一致,基於行/混合模式的:主從數據時一致;

建議:在複製模式下,需要用到UUID()函數,則一定要使用基於行/混合模式複製方式。

名詞解釋:

對於輸入參數相同,且同一時間執行或一個SQL中多處調用,而得到不同值得函數,我們就稱其爲:不確定性函數。

備註:

在MySQL 5.1.*及更高版本有一個變種的UUID()函數,名稱:UUID_SHORT(),生成一個64位無符號的整數,例如:

root@localhost : (none) 02:46:42> SELECT UUID_SHORT()\G

***************** 1. row *****************

UUID_SHORT(): 6218676250261585921

1 row in set (0.00 sec)

後續加註:

UUID()函數產生的值,並不適合作爲InnoDB引擎表的主鍵,至於詳細的原因,請閱讀文章InnoDB引擎表的主鍵選型。

UUID做主鍵,好還是不好?這是個問題。

http://mlxia.iteye.com/blog/279059

作者:老王

我唯一還算熟悉的數據庫就算是MySQL了,大概使用MySQL的人,百分之九九以上的人會使用Autoincrement ID做主鍵,這是可以理解的,因爲MySQL的自增ID效率很高,使用也很方便。那麼剩下的百分之一的人使用什麼做主鍵呢?可能是自己做的KeyGenerator,也可能是我們下面要說的UUID。

據說在Oracle的圈子裏,如果誰用自增ID做主鍵是要被鄙視的,主鍵最自然的選擇就是UUID。我不瞭解Oracle,這些道聽途說的結論是否正確不做承諾。

那麼我們先看看什麼是UUID?簡單的說,UUID是指在一臺機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的。在UUID的算法中,可能會用到諸如網卡MAC地址,IP,主機名,進程ID等信息以保證其獨立性。

如果你的MySQL版本不太老的話,鍵入 SELECT UUID(); 輸出的就是UUID,如下:

mysql> select uuid();
+————————————–+
| uuid() |
+————————————–+
| 54b4c01f-dce0-102a-a4e0-462c07a00c5e |
+————————————–+

現在大家應該對UUID有一個比較直觀的認識了,我們來看看UUID的優缺點分別是什麼。

優點:

能夠保證獨立性,程序可以在不同的數據庫間遷移,效果不受影響。
保證生成的ID不僅是表獨立的,而且是庫獨立的,這點在你想切分數據庫的時候尤爲重要。

缺點:

比較佔地方,和INT類型相比,存儲一個UUID要花費更多的空間。
使用UUID後,URL顯得冗長,不夠友好。

下面針對上述UUID的缺點說說我的看法,比較佔地方這個缺點我不是很在乎,現在最不值錢的就是硬盤了,略過此條缺點無妨。至於說使用UUID後,URL顯得不友好,我覺得這多少是你的INT情結造成的慣性思維,其實,和INT類型相比,UUID纔是最自然的主鍵選擇,注意,我這裏用的是自然這個形容詞,仔細體會一下你能理解我的意思。另外,很多時候,URL本身就不需要友好,比如,一個電子商務網站,按照INT友好的URL說法,她的訂單URL大概是下面這個形式的:/order.php/id/123,我要說明的是,這樣是很友好,但是有些太友好了,友好的甚至不安全,比如說,我早晨下一個訂單,發現URL是/order.php/id/1000,晚上再下一個訂單發現URL是/order.php/id/2000,那麼我就可以估計出此網站一天的訂單數大致是1000左右,甚至能大體估計出它的銷售額,而這些數據往往都是重要的商業祕密。使用UUID就沒有這個顧慮。

效率?

如果上面說的UUID的所謂缺點都不成立的話,那麼是否使用UUID做主鍵,唯一的問題就是效率了。據說在PostgreSQL等數據庫裏,都有專門的UUID類型,在這樣的數據庫裏,使用UUID做主鍵,效率沒有任何問題,可惜在MySQL裏沒有這樣的字段,如果想在MySQL裏保存UUID做主鍵,一般是使用CHAR(36)來模擬,因爲不是一個原生的UUID類型,所以主鍵的效率到底如何有待測試,另外,UUID做主鍵的效率和UUID本身的算法實現也有很大關係。

我本來想在我自己的電腦上插入1000000條數據測試一下看看來着,可惜一測試,硬盤燈就一直亮,讓我很擔心它會掛,雖然硬盤不值錢,但是我重要的數據都在上面,一旦壞了,損失就大了,所以,測試只好作罷。

至於在MySQL上使用UUID(用char(36)存儲)做主鍵,效率到底如何,我也不知道,抱歉 -_-!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章