日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

选择主键:自然键还是代理键?

發(fā)布時間:2025/5/22 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 选择主键:自然键还是代理键? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【轉(zhuǎn)自】http://blog.csdn.net/haiross/article/details/21388997
【原文地址】http://www.agiledata.org/essays/keys.html

本文概述關(guān)系數(shù)據(jù)庫中為表指定主鍵的策略。主要關(guān)注于何時使用自然鍵或者代理鍵的問題。有些人會告訴你應(yīng)該總是使用自然鍵,而另外一些人會告訴你應(yīng)該總是使用代理鍵。這些人總是被證明是錯誤的,通常他們僅僅是與你分享了他們“數(shù)據(jù)信仰”的偏見。事實上自然鍵與代理鍵具有各自的優(yōu)缺點,沒有在所有情況下都完美的策略。也就是說,你必須清楚你要做的事情才能做好它。本文討論以下內(nèi)容:

常用的術(shù)語
選擇鍵的策略
代理鍵實現(xiàn)策略
有效選鍵的技巧
做出了“錯誤”選擇時如何應(yīng)對

1 常用的術(shù)語

讓我們從描述一些關(guān)于鍵的常用術(shù)語開始,然后再看一個示例。這些術(shù)語包括:

1.鍵。鍵是唯一標(biāo)識一個實體的一個或者多個數(shù)據(jù)屬性。在物理數(shù)據(jù)庫中,鍵可以由表的一個或者多個列組成,它們的值唯一標(biāo)識關(guān)系表中的一行。

2.復(fù)合鍵。由兩個或者多個屬性組成的鍵。

3.自然鍵。由現(xiàn)實世界中已經(jīng)存在的屬性組成的鍵。例如,美國公民被分配了一個唯一(不保證一定正確,但實際上非常接近唯一)的社會保險號(SSN)。如果隱私法允許的話,SSN可能被用作Person實體的自然鍵(假設(shè)組織的人員范圍僅限于美國)。

4.代理鍵。不具有業(yè)務(wù)含義的鍵。

5.候選鍵。在邏輯數(shù)據(jù)模型中的實體類型可能具有0或多個候選鍵,簡稱為唯一標(biāo)識(注解:某些人不主張在邏輯數(shù)據(jù)模型中標(biāo)識候選鍵,因此沒有固定標(biāo)準(zhǔn))。例如,假設(shè)我們只涉及美國公民,那么SSN是Person實體類型的一個候選鍵,同時姓名與電話號碼的組合(假設(shè)組合是唯一的)是第二個可能的候選鍵。這兩個鍵都被稱作候選鍵是因為它們是物理數(shù)據(jù)模型中主鍵、次鍵或者非鍵的候選目標(biāo)。

6.主鍵。實體類型的首選鍵。

7.備用鍵。也就是次鍵,是表中行的另一個唯一標(biāo)識。

8.外鍵。在一個實體類型中表示另一個實體類型的主鍵或者次鍵的一個或多個屬性。

圖1顯示了使用UML符號描述的實際地址的物理數(shù)據(jù)模型。在圖1中,表Customer使用CustomerNumber作為主鍵而SocialSecurityNumber作為備用鍵。這就意味著訪問顧客信息的首先方法是通過一個人的顧客編號,雖然軟件使用社會保險號也能夠獲得相同的信息。表CustomerHasAddress擁有一個復(fù)合鍵,由CustomerNumber與AddressID組成。外鍵是一個實體類型中,代表另一個實體類型的主鍵或者次鍵的一個或多個屬性。外鍵用于維護(hù)數(shù)據(jù)行之間的關(guān)聯(lián)。例如,表CustomerHasAddress與表Customer中行之間的關(guān)聯(lián)通過表CustomerHasAddress的CustomerNumber列進(jìn)行維護(hù)。有趣的是列CustomerNumber既是表CustomerHasAddress主鍵的一部分,又是表Customer的外鍵。同樣,列AddressID既是表CustomerHasAddress主鍵的一部分,又是表Address的外鍵,維護(hù)這兩個表中行的關(guān)聯(lián)。


圖1 一個包含Customer與Address的簡單PDM

2 比較自然鍵與代理鍵策略

為表指定鍵的策略有兩種:

1.自然鍵。自然鍵是已經(jīng)存在的一個或多個屬性,它在業(yè)務(wù)概念中是唯一的。對于表Customer來說,存在兩個候選鍵,CustomerNumber與SocialSecurityNumber。

2.代理鍵。引入一個不具有業(yè)務(wù)含義的列作為鍵,稱作代理鍵。例如圖1中表Address的列AddressID。地址不具有一個“簡單”的自然鍵,因為需要使用Address表的所有列組成一個鍵(取決于你的問題域,可能僅僅需要組合Street和ZipCode列),所以此時引入一個代理鍵是一個更好的選擇。
自然鍵的優(yōu)點是它們已經(jīng)存在,不需要在數(shù)據(jù)模式中引入一個新的“非自然”列。然而,自然鍵的缺點是由于具有業(yè)務(wù)含義,它們與業(yè)務(wù)直接耦合:你可能在業(yè)務(wù)需求變更時重新指定鍵。例如,當(dāng)你的用戶決定將CustomerNumber列從數(shù)字型改為字母數(shù)字型,除了更新表Customer的模式(這個是不可避免的)外,你還需要修改每一個使用CustomerNumber作為外鍵的表。

代理鍵具有幾個優(yōu)點。首先,它們不與業(yè)務(wù)耦合,因此更容易維護(hù)(假設(shè)你選擇了一個好的實現(xiàn)策略)。例如,如果表Customer改為使用代理鍵,修改只需要在表Customer內(nèi)部進(jìn)行(此時CustomerNumber只是表的一個非鍵列)。當(dāng)然,如果你需要針對代理鍵策略做相似的變更,可能是由于用完了所有的值而需要增加幾個位數(shù),將會面臨同樣的問題。其次,一個大多數(shù)表,最好是全部表,通用的鍵策略能夠減少需要編寫的源碼數(shù)量,減少系統(tǒng)的總體擁有成本(TCO)。代理鍵根本的缺點是它們通常不是“人可讀的”,導(dǎo)致終端用戶難以使用。這意味著你可能仍然需要實現(xiàn)代理鍵用于查找、編輯等等。

根本問題在于鍵是關(guān)系模式中重要的耦合源,因此它們很難更改。這意味著你通常想要避免具有業(yè)務(wù)含義的鍵,因為業(yè)務(wù)含義存在變化。話雖如此,我傾向于使用自然鍵查找/引用表,尤其當(dāng)我認(rèn)為鍵值在最近不會改變時,如下文所述。從根本上講,是否應(yīng)該優(yōu)先使用自然鍵沒有明確的答案,不管這個宗教之爭的另外一方狂熱者如何聲稱,最好的策略是只要有意義就可以使用任何一個策略。

3 代理鍵實現(xiàn)策略

實現(xiàn)代理鍵有幾個常用的選擇:

1.使用數(shù)據(jù)庫賦值。大多數(shù)主要的數(shù)據(jù)庫供應(yīng)商–例如Oracle、Sybase以及Informix–實現(xiàn)了被稱為遞增鍵的代理鍵策略。基本理念是在數(shù)據(jù)庫服務(wù)器中維護(hù)一個計數(shù)器,將當(dāng)前值寫入一個隱藏的系統(tǒng)表來維護(hù)一致性,并用于賦值一個新建的數(shù)據(jù)行。每創(chuàng)建一行,計數(shù)器遞增并將值作為該行的鍵值。不同供應(yīng)商的實現(xiàn)策略不同,有時候值在所有表之間都是唯一的,有時候只在單個表內(nèi)部是唯一的,但是基本概念相同。

2.MAX() + 1。一個常用的策略是使用整數(shù)列,第一條記錄從1開始,然后新行的值設(shè)置為該列的最大值加1,最大值用SQL函數(shù)MAX獲得。雖然這個方法簡單,但是對于大表存在性能問題,而且它只能確保表內(nèi)部的唯一鍵值。

3.全局唯一標(biāo)識符(UUIDs)。GUIDs是128位值,來自以太網(wǎng)卡ID或等價的軟件表示以及系統(tǒng)當(dāng)前時間的哈希值。該算法是由開放軟件基金會定義的。

4.全球唯一標(biāo)識(GUIDs)。GUIDs是微軟擴(kuò)展UUIDs后的標(biāo)準(zhǔn),遵從相同的策略,如果存在以太網(wǎng)卡使用網(wǎng)卡ID,如果不存在,使用軟件ID與當(dāng)前時間計算一個哈希值,確保在機(jī)器內(nèi)部唯一。

5.高低位策略。它的基本思想是鍵值,通常稱為持久化對象標(biāo)識符(POID)或者簡稱對象標(biāo)識符(OID),分為兩個邏輯部分:從指定來源獲取的唯一HIGH值和應(yīng)用自身分配的N為LOW值。每獲取一個HIGH值,LOW值設(shè)置為0。例如,應(yīng)用請求一個HIGH值并被賦予1701。假設(shè)LOW值的位數(shù)N為4,那么賦予對象的POID將會由17010000、17010001、17010002等等直到17019999組成。此時,再獲取一個新的HIGH值,LOW值設(shè)置為0,再次重復(fù)。如果另一個應(yīng)用在之后立即請求了一個HIGH值,它將獲得1702,而它創(chuàng)建的對象被賦予OIDs將會是17020000、17020001等等。正如你所看到的,只要HIGH值唯一,所有的POID值將會唯一。在www.theserverside.com上可以找到一個HIGH-LOW發(fā)生器的實現(xiàn)。

根本問題在于鍵是關(guān)系模式中重要的耦合源,因此它們很難重構(gòu)。這意味著你通常想要避免具有業(yè)務(wù)含義的鍵,因為業(yè)務(wù)含義存在變化。然而,同時你需要記住某些數(shù)據(jù)通常是通過唯一標(biāo)識進(jìn)行訪問,例如通過顧客編號訪問顧客信息,通過社會保險號訪問美國雇員信息。在這種情況下你可能想要使用自然鍵而不是UUID或者POID這樣的代理鍵。

4 有效選鍵技巧

如何有效地選擇鍵?參考以下提示:

1.避免“智能”鍵。“智能”鍵是由一個或多個具有業(yè)務(wù)含義的部分組成的鍵。例如,美國郵政編碼的前兩位表示它所在的州。智能鍵的第一個問題是它具有業(yè)務(wù)含義。其次是它們的使用通常隨著時間變得很復(fù)雜。例如,一些大的州擁有多個代碼,加利福尼亞的郵編以90和91開頭,導(dǎo)致基于州編碼的查詢更加復(fù)雜。第三個問題是它們通常增加了策略需要進(jìn)行擴(kuò)展的可能性。考慮長度為9位數(shù)字的郵編(后4位數(shù)字由建筑所有者自行決定,建筑由郵編唯一標(biāo)識),在用完2位州代碼前用完9位數(shù)字的可能性更小。

2.考慮為簡單的“查找”表指定自然鍵。“查找”表是用于關(guān)聯(lián)代碼與詳細(xì)信息的表。例如,你可能擁有一個列出了顏色代碼對應(yīng)顏色名稱的查找表。例如,代碼127代表“郁金香黃色”。簡單的查找表通常包含一個代碼列和一個描述/名稱列,而復(fù)雜的查找表包含一個代碼列和幾個信息列。

3.自然鍵并非總是適用于“查找”表。另一個例子是一個查找表包含北美洲的州、省或者地區(qū)。例如美國的加利福尼亞州以及加拿大的安大略省。該表的主要目的是為這些地理位置提供一個正式的列表,它不會隨時間變化(最近一次變化是90年代后期,加拿大的西北地區(qū)分割為努勒維特和西北地區(qū))。該表的一個有效自然鍵可以是州代碼,一個值唯一的兩字符代碼–例如加利福尼亞的CA以及安大略的ON。不幸的是這種方法并不適合,因為加拿大政府決定為西北地區(qū)兩個州使用相同的代碼NW。

4.應(yīng)用必須仍然支持“自然鍵搜索”。如果選擇采用代理鍵,必須不能忘了應(yīng)用需要支持基于地域列(仍然唯一標(biāo)識數(shù)據(jù)行)的搜索。例如,Customer表可能擁有一個Customer_POID的代理鍵,以及一個Customer_Number列和Social_Security_Number列。你很可能需要支持基于顧客編號和社會保險號的搜索。搜索在關(guān)系數(shù)據(jù)庫對象檢索最佳實踐中詳細(xì)討論。

5.不要自然化代理鍵。一旦你向終端用戶顯示了代理鍵的值,或者更壞的是允許他們使用該值(例如搜索該值),實際上你已經(jīng)給它們賦予了業(yè)務(wù)含義。這實際上是自然化了代理鍵從而失去了代理鍵的優(yōu)點。

5 做出了“錯誤”選擇時如何應(yīng)對

首先,不用為此擔(dān)心:不論你多么擅長數(shù)據(jù)庫設(shè)計都可能會犯錯。好消息是正如我在數(shù)據(jù)庫重構(gòu)過程中所說,雖然可能需要許多工作,還是可以使用代理鍵替換自然鍵的(反之亦然)。要使用代理鍵替換自然鍵,你需要應(yīng)用引入代理鍵重構(gòu),如圖2所示。要使用自然鍵替換代理鍵,你需要應(yīng)用使用自然鍵替換代理鍵重構(gòu),如圖3所示。

圖2 替換表Order的自然鍵


圖3 替換表State的代理鍵

總結(jié)

以上是生活随笔為你收集整理的选择主键:自然键还是代理键?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。