數據庫主鍵設計之思考[轉]

 

http://edu.yesky.com/edupxpt/94/2146594.shtml
  主鍵的必要性:
  有些朋友可能不提倡數據庫表必需要主鍵,但在個人思考中,以爲每一個表都應該具備主鍵,不論是單主鍵仍是雙主鍵,主鍵的存在就表明着表結構的完整性,表的記錄必須得有惟一區分的字段,主鍵主要是用於其餘表的外鍵關聯,本記錄的修改與刪除,當咱們沒有主鍵時,這些操做會變的很是麻煩。
  主鍵的無心義性:
  我強調主鍵不該該具備實際的意義,這可能對於一些朋友來講不太認同,好比訂單表吧,會有「訂單編號」字段,而這個字段呢在業務實際中自己就是應該具備惟一性,具備惟一標識記錄的功能,但我是不推薦採用訂單編號字段做爲主鍵的,由於具備實際意義的字段,具備「意義更改」的可能性,好比訂單編號在剛開始的時候咱們一切順利,後來客戶說「訂單能夠做廢,並從新生成訂單,並且訂單號要保持原訂單號一致」,這樣原來的主鍵就面臨危險了。所以,具備惟一性的實際字段也表明能夠做爲主鍵。所以,我推薦是新設一個字段專門用爲主鍵,此主鍵自己在業務邏輯上不體現,不具備實際意義。而這種主鍵在必定程序增長了複雜度,因此要視實際系統的規模大小而定,對於小項目,之後擴展不會很大的話,也查容許用實際惟一的字段做主鍵的。
  主鍵的選擇
  咱們如今在思考一下,應該採用什麼來做表的主鍵比較合理,申明一下,主鍵的設計沒有一個定論,各人有各人的方法,哪怕同一個,在不一樣的項目中,也會採用不一樣的主鍵設計原則。
  第一:編號做主鍵
  此方法就是採用實際業務中的惟一字段的「編號」做爲主鍵設計,這在小型的項目中是推薦這樣作的,由於這可使項目比較簡單化,但在使用中卻可能帶來一些麻煩,好比要進行「編號修改」時,可能要涉及到不少相關聯的其餘表,就象黎叔說的「後果很嚴重」;還有就是上面提到的「業務要求容許編號重複時」,咱們再那麼先知,都沒法知道業務將會修改爲什麼?
  第二:自動編號主鍵
  這種方法也是不少朋友在使用的,就是新建一個ID字段,自動增加,很是方便也知足主鍵的原則,優勢是:數據庫自動編號,速度快,並且是增量增加,彙集型主鍵按順序存放,對於檢索很是有利;數字型的,佔用空間小,易排序,在程序中傳遞也方便;若是經過非系統增長記錄(好比手動錄入,或是用其餘工具直接在表裏插入新記錄,或老系統數據導入)時,很是方便,不用擔憂主鍵重複問題。
  缺點:其實缺點也就是來自其優勢,就是由於自動增加,在手動要插入指定ID的記錄時會顯得麻煩,尤爲是當系統與其餘系統集成時,須要數據導入時,很難保證原系統的ID不發生主鍵衝突(前提是老系統也是數字型的);若是其餘系統主鍵不是數字型那就麻煩更大了,會致使修改主鍵數據類型了,這也會致使其餘相關表的修改,後果一樣很嚴重;就算其餘系統也是數字型的,在導入時,爲了區分新老數據,可能想在老數據主鍵前統一加一個「o」(old)來表示這是老數據,那麼自動增加的數字型又面臨一個挑戰。
  第三:Max加一
  因爲自動編號存在那些問題,因此有些朋友就採用本身生成,一樣是數字型的,只是把自動增加去掉了,採用在Insert時,讀取Max值後加一,這種方法能夠避免自動編號的問題,但也存在一個效率問題,若是記錄很是大的話,那麼Max()也會影響效率的;更嚴重的是併發性問題,若是同時有兩人讀到相同的Max後,加一後插入的ID值會重複,這已是有經驗教訓的了。
  第四:自制加一
  考慮Max加一的效率後,有人採用自制加一,也就是建一個特別的表,字段爲:表名,當前序列值。這樣在往表中插入值時,先今後表中找到相應表的最大值後加一,進行插入,有人可能發現,也可能會存在併發處理,這個併發處理,咱們能夠採用lock線程的方式來避免,在生成此值的時,先Lock,取到值之後,再unLock出來,這樣不會有兩人同時生成了。這比Max加一的速度要快多了。但一樣存在一個問題:在與其餘系統集成時,脫離了系統中的生成方法後,很麻煩保證自制表中的最大值與導入後的保持一致,並且數字型都存在上面講到的「o」老數據的導入問題。所以在「自制加一」中能夠把主鍵設爲字符型的。字符型的自制加一我卻是蠻推薦的,應該字符型主鍵能夠應付不少咱們意想不到的狀況。
  第五:GUID主鍵
  目前一個比較好的主鍵是採用GUID,固然我是推薦主鍵仍是字符型的,但值由GUID生成,GUID是能夠自動生成,也能夠程序生成,並且鍵值不可能重複,能夠解決系統集成問題,幾個系統的GUID值導到一塊兒時,也不會發生重複,就算有「o」老數據也能夠區分,並且效率很高,在.NET裏能夠直接使用System.Guid.NewGuid()進行生成,在SQL裏也可使用 NewID()生成。優勢是:
  同 IDENTITY 列相比,uniqueidentifier 列能夠經過 NewID() 函數提早得知新增長的行 ID,爲應用程序的後續處理提供了很大方便。
  便於數據庫移植,其它數據庫中並不必定具備 IDENTITY 列,而 Guid 列能夠做爲字符型列轉換到其它數據庫中,同時將應用程序中產生的 GUID 值存入數據庫,它不會對原有數據帶來影響。
  便於數據庫初始化,若是應用程序要加載一些初始數據, IDENTITY 列的處理方式就比較麻煩,而 uniqueidentifier 列則無需任何處理,直接用 T-SQL 加載便可。
  便於對某些對象或常量進行永久標識,如類的 ClassID,對象的實例標識,UDDI 中的聯繫人、服務接口、tModel標識定義等。
  缺點是:
  GUID 值較長,不容易記憶和輸入,並且這個值是隨機、無順序的。
  GUID 的值有 16 個字節,與其它那些諸如 4 字節的整數相比要相對大一些。這意味着若是在數據庫中使用 uniqueidentifier 鍵,可能會帶來兩方面的消極影響:存儲空間增大;索引時間較慢。
  我也不是推薦GUID最好,其實在不一樣的狀況,咱們均可以採用上面的某一種方式,思考了一些利與弊,也方便你們在進行設計時參考。這些也只是個人一點思考而已,並且可能我知識面限制,會有一些誤論在裏面,但願你們有什麼想法歡迎討論。

0javascript

收藏css

不破樓蘭

57篇文章,9W+人氣,0粉絲

Ctrl+Enter 發佈html

發佈java

取消jquery

掃一掃,領取大禮包linux

0git

分享
不破樓蘭
相關文章
相關標籤/搜索