作者:Sinte-Beuve;
鏈接:www.cnblogs.com/Sinte-Beuve


談談實際項目中對 數據庫設計 的一些思考

注:本人開發經驗尚淺,下文主要談的是自己的一些想法,不足之處請指出。

最近半年時間都花在管理系統的開放上面,對數據庫的設計有一些自己的想法,在我看來數據庫設計的key point就是妥協。一個設計的比較好的數據庫都是在業務邏輯、設計規約和便於開發這三者之前來回考量,從而獲得3-win的結果。下面主要是在思考和總結的點。

如何設計出高靈活性的數據庫

可以說在項目交付前,需求不斷在變,如何在需求改變的同時儘可能減少對錶結構的修改是我現在考慮的問題。對於一般情況而言,在設計的時候我們可以適當添加一些預留的字段,需求改變的時候可以用上,或者說是添加不足的字段。

但是也會出現一些比較麻煩的情況——舊錶不足以進行修改維護,需要局部重新設計,這就會給開發帶來比較多的麻煩,因爲大多現在我們都會使用ORM。

eg1:

在貸款的業務流程中,每一筆借款申請需要進行審覈。

起初,參與的審覈角色只有2名,所以我選擇了,直接添加字段到貸款申請表中。

之後,參與審覈的角色數變多,並且審覈產生的業務參數變多(例如各類附件、意見等),直接添加字段到貸款表中顯得不那麼合理,同時不利於審覈流程的體現。因此,這一部分需要單獨重新設計,根據業務流的需要,將審覈的事件單獨拉出來一張表,通過外鍵關聯到申請表中。(流程複復雜可參考工作流引擎的設計思路)

這個案例裏,最初的設計,覺得既然審覈人數少,直接把審覈信息添加到申請表中即可,不需要單獨建表,也方便了開發,但是後來的需求改變就有單措手不及了。

這裏就感覺很矛盾,同時也發現數據庫的設計居然也和軟件工程那一套理論驚人的相似。在軟件工程裏面,我們經常會聽到一句話“低耦合、高內聚”,一般是提醒我們,儘可能保證模塊與模塊之間相互獨立,減少不必要的依賴關係。

談談實際項目中對 數據庫設計 的一些思考


這也就是困擾這我的地方,如果一開始設計就考慮單一職責,分成兩張表,未免顯得有些複雜化了,也不利於開發(需要維護1-n的關係)。畢竟代碼一定程度上是可以重構的。

數據庫原理在實際設計中的運用

我們在《數據庫原理與設計》中學過很多的概念,由於實驗環境的限制(數據量小、課設的業務偏簡單etc.),導致很多概念在那時真的就變成了一個死記硬背的概念。這點或許隨着開發經驗的增長會豁然開朗吧。下面介紹幾個,替他們刷一下存在感,內容都很淺,但也希望對在學習數據庫的有一點幫助吧。

範式(NF)

1NF的定義爲:符合1NF的關係中的每個屬性都不可再分2NF在1NF的基礎之上,消除了非主屬性對於碼的部分函數依賴。3NF在2NF的基礎之上,消除了非主屬性對於碼的傳遞函數依賴。…

範式的概念大家肯定背的很熟,本人研究生面試也考了這個。這一點其實大家在按設計數據庫的時候都已經用上了。明確實體間的關係,畫E-R圖,其實就是對範式的運用。

索引(Index)

Index,面試的時候也經常會問到,但是呢學他的時候基本上感覺不到他的存在,畢竟測試的數據集太小了。底層的原理牽扯到數據結構,這裏就不展開了。但是需要知道的是:

  • 需要做表連接的字段,需要添加index。
  • 經常需要查詢的字段,需要添加index。
  • 很多字段需要聯查的時候,需要添加組合查詢。

下面是一個實際項目中的例子,可以感受下:

有一個地方需要數據展示,需要多表聯查。下面就是建索引和不建索引的區別了。

談談實際項目中對 數據庫設計 的一些思考


談談實際項目中對 數據庫設計 的一些思考


事務(Transaction)

數據庫事務(Database Transaction) ,是指作爲單個邏輯工作單元執行的一系列操作,要麼完全地執行,要麼完全地不執行。

事務處理可以確保除非事務性單元內的所有操作都成功完成,否則不會永久更新面向數據的資源。通過將一組相關操作組合爲一個要麼全部成功要麼全部失敗的單元,可以簡化錯誤恢復並使應用程序更加可靠。一個邏輯工作單元要成爲事務,必須滿足所謂的ACID(原子性、一致性、隔離性和持久性)屬性。事務是數據庫運行中的邏輯工作單位,由DBMS中的事務管理子系統負責事務的處理。

這個寫過管理系統的應該都明白。大概就是下面這個模型。JDBC中就有,在ssh或ssm中可以配合註解或配置文件來實現。

BeginTransaction{
// to-do
commit
}catch{
rollback
}

一般在多表操作時必須使用事務!例如級聯刪除,多表修改。如果不使用,一旦出現異常,會導致數據不一致!

具體可參考:

http://www.mybatis.org/spring/zh/transactions.htmlhttps://www.cnblogs.com/Weagle/p/5264450.html

鎖(lock)

鎖根據不同的法,可以分爲樂觀鎖、悲觀鎖。也可以分爲共享鎖和排它鎖。

一般在出現併發問題的時候會用到鎖,具體可以看我另外一篇:

http://www.cnblogs.com/Sinte-Beuve/p/7631745.html

解決小規模併發下單問題。裏面詳細講了鎖的描述和實現。

筆者經驗有限,其實還有很多概念類似,數據庫安全,容災備份等沒有接觸到的,希望以後有機會可以補全。

冗餘字段的利用

冗餘字段的利用,其實僅僅是爲了開發方便的一個tip。

談談實際項目中對 數據庫設計 的一些思考


談談實際項目中對 數據庫設計 的一些思考


具體可以看上面一個小例子。一筆借款需要經過很多人的審覈才能通過。因此存在借款表和審覈流程表,兩者一對多。通過借款單號可以去審覈表中查詢其所有的審覈情況。

那麼此時,我選擇在借款表中存審覈流程表id(外鍵)的同時,存下當前這一筆借款的審覈信息。這麼做的好處就是,我不需要去做表連接,直接可以查詢到借款的當前進行到哪一流程,或者說申請失敗,失敗在哪一流程。從開發的角度,如果有一個頁面需要顯示出借款的當前流程,那就可以輕鬆查詢到了。

畢竟,處理表連接操作是相對麻煩的,同時效率並不高。因此在存儲條件允許的情況下,可以通過適當冗餘來減少開發中的麻煩。這裏就體現了數據庫設計的一種妥協,現在存在冗餘是違反了2-NF的,所以有的時候就需要憑經驗來進行調整。對於不是頻繁需要修改的字段,是可以適當冗餘存取的,反之,經常需要修改的字段,如果冗餘存取,一不小心很容易造成數據的不一致,就不建議了。

視圖與冗餘表

在談冗餘表前,先來看幾個在Java OO中的概念,拋磚引玉一下。

VO(View Object):視圖對象,用於展示層,它的作用是把某個指定頁面(或組件)的所有數據封裝起來。DTO(Data Transfer Object):數據傳輸對象,這個概念來源於J2EE的設計模式,原來的目的是爲了EJB的分佈式應用提供粗粒度的數據實體,以減少分佈式調用的次數,從而提高分佈式調用的性能和降低網絡負載,但在這裏,我泛指用於展示層與服務層之間的數據傳輸對象。DO(Domain Object):領域對象,就是從現實世界中抽象出來的有形或無形的業務實體。PO(Persistent Object):持久化對象,它跟持久層(通常是關係型數據庫)的數據結構形成一一對應的映射關係,如果持久層是關係型數據庫,那麼,數據表中的每個字段(或若干個)就對應PO的一個(或若干個)屬性。

首先,這些對象其實是和數據庫中數據表存在一些關係的。我想說的是,在數據展示或數據傳輸時,可能會涉及多張表,這個時候我們會做的就是創建一個新的Object,然後講多張表對應的持久化對象放進去,或者直接從多個表的持久化對象中抽取需要的字段。這個對象也就是上面提到的VO和DTO了。

這種做法同時也可以在數據庫進行實現,那就是冗餘表。其實也就是把很多張表的數據統一到一張表中去,爲的也是查詢和更新的方便。

之前遇到以下這個業務:

存在訂單、訂單明細之前一對多,訂單又需要和卡綁定,一對多。現在我需要將數據一起顯示出來看,同時粒度要最細,以訂單明細和卡號的形式顯示出來,t同時可更新。

eg:有訂單記錄A ,訂單明細B1、B2,綁定了兩張卡C1、C2,那麼顯示效果如下

C1 A B1
C1 A B2
C2 A B1
C2 A B2

這個時候考慮到如果創建一個DTO來保存這些數據的話,在查詢組裝上需要花很多的時間,於是就直接創建了一張冗餘表,用於維護這層關係。那麼通過這層冗餘表查詢出來的結果就是可以直接用於顯示的,更新的時候也只需要直接找到外鍵進行更新就可以了。

我覺得使用DTO還是冗餘表,完全就是取決於開發上的的便利以及是否需要對數據進行持久化了。

同樣的,之前的例子提到是需要對數據進行更新或刪除的,如果僅僅是爲了數據的展示,例如一些統計數據的展示。那麼就不需要冗餘表了。數據庫裏面有個專有的概念——視圖。比如說查詢每天每年每季度的銷售情況等等,直接用sql創建視圖,查詢以天爲單位的結果,展示的時候直接從view中取數據即可,將複雜的sql語句就留在數據庫那邊了。

當然創建視圖若使用大量表連接時,記得創建index進行優化,否則查詢效率會很低。

數據字典與代碼表

數據字典與代碼表其實存儲的就是一些常量了。

數據字典一般兩張表,一張存類別,一張存鍵值對。數據字典一般用於存取一些不太會變的數據,例如性別、訂單狀態etc。而且這些數據量比較小,可以統一存儲。

代碼表,一般都是各管各存儲的。例如文章分類表、標籤表、省市區代碼、商品分類etc。這些本來數據就大,並且有一定的業務性,有些會隨着業務的擴大而變動,因此單獨存表會比較好。

總結

一下子碼了很多字,主要寫了一些數據庫中的一些概念在實際應用上的體現。表達了最近一段時間對數據庫設計上面的一些思考和見解。人是會思想的蘆葦,實踐是檢驗真理的唯一標準,嗯……

相關文章