數據庫主鍵設計思考-五大策略

     關於主鍵的故事,生動形象的描述了數據庫中主鍵的作用,也部分闡述了各種不同數據庫主鍵設計的優缺點,此處更詳細的對數據主鍵的設計策略做引用總結,以供參考!

 

     關於數據庫中主鍵設計:

     主鍵的必要性:

     個人覺得每個表都應該具有主鍵,不管是單主鍵還是雙主鍵,主鍵的存在就代表着表結構的完整性,表的記錄必須得有唯一區分的標識,主鍵主要是用於作爲其他表的外鍵關聯、以及本記錄的修改與刪除操作,如果沒有該對象的標識,這些操作會變的非常麻煩。

     主鍵的無意義性:
     這裏強調主鍵不應該具有實際的意義,提出對象屬性和對象標識都是對象數據庫中的概念。 什麼是對象屬性呢?就是業務邏輯上涉及的任何可變信息,什麼“姓名”、“性別”、“身份證號”、“訂單號”...通通都是對象屬性。對象屬性總會變化的,只是有些變得快,有些變得慢而已。 對象標識是啥?就是唯一區分數據對象的鑑別符,對象標識存在的唯一目的就是區分對象,除此之外沒有任何業務邏輯上的意義。無論對象的屬性值怎樣變化,但對象還是對象,也就是說對象的本質沒有變,這種唯一表示對象本身的東西,就是對象標識,也就是對象的主鍵!此對象標識本身業務邏輯上不體現,不具有實際意義。
   
     現在在思考一下,應該採用什麼來作表的主鍵比較合理,其實主鍵的設計沒有一個定論,各人有各人的方法,哪怕同一個,在不同的項目中,也會採用不同的主鍵設計原則。 下面提供五大常用主鍵的設計策略:
     第一:編號作主鍵
     此方法就是採用實際業務中的唯一字段的“編號”作爲主鍵設計,這在小型的項目中是推薦這樣做的。

     優點:這可以使項目比較簡單化

     缺點:在使用中可能帶來一些麻煩,比如要進行“編號修改”時,可能要涉及到很多相關聯的其他表,如果業務要求允許編號重複時,我們再那麼先知,都無法知道業務將會修改成什麼?

     第二:自動編號主鍵  
     這種方法也是很多朋友在使用的,就是新建一個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最好,其實在不同的情況,我們都可以採用上面的某一種方式,思考了一些利與弊,也方便大家在進行設計時參考。這些也只

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