博主認為,設計的依據在於三種因素:
1、正確
1、表達清晰
2、效率
針對數據庫的設計,經常考慮兩個因素:
1、實體成為屬性還是表
2、二元關系還是多元關系
第一條不用多說,如果設計出來的模型不能正確反映想要表達的實體和各種約束,這自然是失敗的設計。至於第二條,如果不注重表達的情緒,一上來就想去考慮有關效率的細節,這樣做很容易陷入迷惑,表達清晰的設計容易理解和維護。容易維護的設計不一定能針對實際需求達到高效率,所以需要優化,比如修改關系模式避免連接操作,以及在物理上建立索引。
首先按照最清晰的方式來進行設計:每個實體集都單獨對應一張表,並且采用多元關系。然后再來考慮效率問題。
如果每個實體集都對應一張表,但如果發現一個實體本身幾乎不包含信息,並且與這個實體相聯系的實體比較少,比如搜索引擎中的一個term或者url字符串,我們實在是沒有必要再為這個實體創建一張表,只需要作為其他實體的某個字段就可以了。不需要每個實體都創建一個 ID 字段,因為實際的查詢用不到這個id字段。如果視圖用 id 作為一個term的標識,與其他實體相聯系,就帶來了連接的代價。總之,應該將字段很少並且和其他實體聯系少的實體刪除,這樣的實體本身只在概念上存在,只出其他實體的字段中;應該將經常需要連接的聯系表刪除,直接在一個實體上添加外鍵字段。
一般來說只要三元關系不過分太長,找不到把多元關系拆分成為多個二元關系的理由,無論是從清晰的角度還是從效率的角度,多元關系往往更加清晰的表達現實世界的概念,同時又避免了連接操作。多個二元關系意味着連接操作,連接操作一般比簡單的過濾查詢費時太多了,建立索引可以緩解查詢問題,它的執行時間不能和連接操作相提並論,比如說考慮用戶-商品-評論關系,某個用戶對某個商品不太可能發表太多的評論,所以三元關系表也不會太長。當然要得到准確的答案還是得根據實際場景進行測試,定性的分析終究不能作為最終判據,一般還是先按照最清晰的方式設計。
兩個二元關系不能表達三元關系!連接操作實際上是找連通路徑的過程,三元聯系關系表的每條記錄代表了一條長度為2的路徑。這些路徑不可能用兩個二元關系表達,因為二元關系的連接操作可能會多出來很多本不存在的三元聯系。必須要引入引用了每條路徑的中間實體,表的長度不會有任何減少。
實體成為屬性還是表?二元關系還是多元關系?相信已經有了更清晰的認識。在概念設計階段我們要讓設計清晰的表達概念,但是在實際邏輯設計階段我們要避免執行可以省去的連接操作。
ps: 一個二元關系對應一個拓撲結構:二分圖的實例。如果二分圖的任意一個連通分支都是一顆根樹,那么這個關系就是一對多、多對一、一對一關系,可以只有一個字段是主鍵;否則是多對多關系,兩個字段都必須是主鍵。
樹和二分圖都是拓撲結構。