1. 程式人生 > >淺談資料庫及表設計的幾個原則

淺談資料庫及表設計的幾個原則

對於資訊管理類的程式來說,一個系統就是一個資訊庫。在大量的資訊中為了索引、區別,最好的辦法就是用資料庫。然而建立一個簡潔、高效、全面的資料庫卻並不簡單。一個優秀的資料庫無疑能夠幫助程式設計師減少業務邏輯操作,減少出錯的可能性;而一個糟糕的資料庫設計會在需要新增功能的時候無從擴 展,或是大量的冗餘造成效能的瓶頸。

因此,建立一個優秀的資料庫,設計好每一張表格變成了尤為重要的事情。然而,很多的問題考慮起來就非常的複雜和繁瑣,且需要對系統的深徹把握和對程式程式碼的經驗積累。但是吵吵認為最好的方式還是“綜合考慮,利弊權衡。”

如何開始你的資料庫設計?

也許你是拿到任務就開始建立表了,user表、product表等等。一張一張的完成,倒是很有速度也很有成就感,但是這絕對是最差的做法。因為你面向的物件是一個系統,而對付這一個系統的時候,你就需要好好思考了。

對於資料庫而言,最簡單的理解方式:資料庫就是一個系統,表就是它的物件,而欄位即是它的屬性。一個確保資料庫事務正確執行的四個基本要素是:

(1) 原子性。基本表中的欄位是不可再分解的。

    (2) 原始性。基本表中的記錄是原始資料(基礎資料)的記錄。

    (3) 演繹性。由基本表與程式碼表中的資料,可以派生出所有的輸出資料。
    (4) 穩定性。基本表的結構是相對穩定的,表中的記錄是要長期儲存的。

基本的原則我們是需要遵照執行的,然而作為一個系統來考慮的話我們不得不考慮其整體的架構了。

就軟體開發而言,這些年來比較熱門的當數“領域驅動設計”了。2004年著名建模專家Eric Evans發表了他最具影響力的書籍:《Domain-Driven Design Tackling Complexity in the Heart of Software》(中文譯名:領域驅動設計軟體核心複雜性應對之道),書中提出了領域驅動設計(簡稱 DDD)的概念。

DDD基於面向物件分析與設計技術,對技術架構進行了分層規劃,同時對每個類進行了策略和型別的劃分。因此“領域驅動設計”能夠指導面向物件開發人 員、系統分析人員和設計人員合理地組織工作,各有側重、彼此協作,有條不紊地進行復雜系統的開發,幫助他們建立豐富而實用的領域模型,並由此建立長期適用 的優質軟體。

按吵吵的理解“領域驅動設計”即是為業務專家和程式設計人員建立了一座溝通的橋樑,一種有效的操作手段和方法,其核心還是領域建模。

這種思想自然是有他的借鑑之處,我們按照“領域驅動設計”的思想建立了一個個獨立的事物類,不同類之間能夠通過各種對映相互影響的話,那麼我們的數 據庫的設計最好的方式是基於這些功能類的設計方法和準則,而不是基於業務和系統了,這樣做的最大好處區分的獨立子系統能夠很好的考慮其效率、冗餘等各方面 的問題了。

正規化設計?

為了建立冗餘較小、結構合理的資料庫,設計資料庫時必須遵循一定的規則。在關係型資料庫中這種規則就稱為正規化。正規化是符合某一種設計要求的總結。要想設計一個結構合理的關係型資料庫,必須滿足一定的正規化。在實際開發中最為常見的設計正規化有三個:

1.第一正規化(確保每列保持原子性)

2.第二正規化(確保表中的每列都和主鍵相關)

3.第三正規化(確保每列都和主鍵列直接相關,而不是間接相關)

按照正規化設計的資料庫最大的好處就是確保了資料庫不會冗餘,結構簡單、穩定。但是,同時帶來的問題就是效能的下降,比如我們有一張表記錄了一條數 據,其中有一個欄位是使用者的ID,並且大部分時候這張表的業務只需要顯示使用者的名稱,至於使用者的密碼、郵箱等資訊都不需要顯示,那麼在這張表中你會加入用 戶名稱這個欄位麼?

這實際上是討論的最多的“關聯”還是不關聯的問題了,很多人說:“當然關聯,不關聯叫什麼關係型資料庫?;但是吵吵也見過一些公司做的專案完全不關聯的,所有的表都是獨立的表的。

關聯的好處:

1、整潔、簡單,獨立性強。從整個系統來看,雖然關聯多出了不少表格,但是每張表都是獨立的,很好的維護了整個系統的簡潔性。

2、將部分邏輯業務交給了DBA,在資料庫介面層注重的是sql查詢語句的編寫,上層業務開發人員可以省下不少力氣。

3、由於關聯的欄位都是用主鍵進行查詢的,減少了出錯的可能性。再者,不關聯的表的記錄的更改可能會涉及到多張表格的同步問題,處理不好也容易出錯。

4、關聯的表多用到sql語句來完成業務與邏輯,而不關聯的表可能要上層程式本身負擔一部分邏輯判斷的任務,這樣子混亂的邏輯與煩雜的判斷,則需要多次封裝繼承。因此關聯還是降低了程式設計師出錯的可能性。

關聯的壞處:

1、反覆的查詢一張固定的表,造成資源的重複浪費,降低了性。

2、查詢一條記錄需要查詢兩張或者以上的表,造成執行時間的延長,降低了伺服器的效能,降低了使用者的體驗。

3、關聯造成的多個外來鍵、連線一定程式上增加了系統的複雜性。

那麼到底該不該關聯,是部分不關聯還是完全不關聯?究竟要不要完全的按照正規化來設計我們的資料庫?這原本就是一個見仁見智的問題。從功能模組出發,從全域性出發,找到綜合處理該問題的平衡點才是最終的王道吧。

NoSQL還是關係型資料庫?

關係型的資料模型定義了高度結構化的資料結構,以及對這些結構之間關係的嚴格定義。通過這些年的發展,關係型資料庫已經提供了相當強大的複雜操作功能,但是由此也引發了一些問題:

1、負載不確定性。使用SQL的一個問題就是計算某個查詢的代價或者產生的負載幾乎是不可能的。使用簡單的查詢語言可能會導致應用層的邏輯更復雜,但是這樣可以將儲存系統的工作簡單化,讓它只需要響應一些簡單的請求。

2、模型嚴格性。對一個問題建模有很多種方式。其中關聯型的資料模型是非常嚴格的一種:表結構的定義規定了表中每一行資料的儲存內容。如果你的資料 結構化並沒有那麼強,或者對每一行資料的要求比較靈活,那可能關聯型的資料模型就太過嚴格了。類似的,應用層的開發人員可能對關聯型的資料結構並不滿意。 比如很多應用程式是用面向物件的語言寫的,資料在這些語言中通常是以列表、佇列或集合的形式組織的,程式設計師們當然希望他們的資料儲存層也能和應用層的資料 模型一致。

3、效能瓶頸。當資料量增長到一臺機器已經不能容納,我們需要將不同的資料表分佈到不同的機器。而為了避免在不同機器上的資料表在進行聯合查詢時需 要跨網路進行。我們必須進行反正規化的資料庫設計,這種設計方式要求我們把需要一次性查詢到的資料儲存在一起。這樣做使得我們的系統變得就像一個主鍵查詢系 統一樣,於是我們開始思考,是否有其它更適合我們資料的資料模型。

“NoSQL”一詞最早於1998年被用於一個輕量級的關係資料庫的名字,而真正現在所說的“NoSQL”概念是2009年提出來的。NoSQL最 常見的解釋是“non-relational”,顧名思義,NoSQL系統的資料操作介面應該是非SQL型別的。但在NoSQL社群,NoSQL被賦予了 更具有包容性的含義,其意為Not Only SQL,即NoSQL提供了一種與傳統關係型資料庫不太一樣的儲存模式,這為開發者提供了在關係型資料庫之外的另一種選擇。

1、擴充套件性。NoSQL資料庫種類繁多,但是一個共同的特點都是去掉關係資料庫的關係型特性。資料之間無關係,這樣就非常容易擴充套件。也無形之間,在架構的層面上帶來了可擴充套件的能力。

2、高效能。NoSQL資料庫都具有非常高的讀寫效能,尤其在大資料量下,同樣表現優秀。這得益於它的無關係性,資料庫的結構簡單。一般MySQL 使用Query Cache,每次表的更新Cache就失效,是一種大粒度的Cache,在針對web2.0的互動頻繁的應用,Cache效能不高。而NoSQL的 Cache是記錄級的,是一種細粒度的Cache,所以NoSQL在這個層面上來說就要效能高很多了。

3、靈活的資料模型。NoSQL無需事先為要儲存的資料建立欄位,隨時可以儲存自定義的資料格式。而在關係資料庫裡,增刪欄位是一件非常麻煩的事情。如果是非常大資料量的表,增加欄位簡直就是一個噩夢。這點在大資料量的web2.0時代尤其明顯。

4、高可用性。NoSQL在不太影響效能的情況,就可以方便的實現高可用的架構。比如Cassandra,HBase模型,通過複製模型也能實現高可用。

截止到今天,雖然還沒有成熟的NoSQL平臺出現,但是像百度、騰訊這種效能要求極高,資料量極大地企業都已經部署了NoSQL的儲存平臺。就NoSQL來講,目前應用的還不是很廣泛,但是在web2.0中產生了大概這三種模式:

1、以NoSQL為主。

2、SQL與NoSQL的相互融合。

3、以NoSQ架構作為快取。

按照現有的趨勢來講,一個數據量極大的系統,部署“雲端計算”是遲早的事情。一方面“雲端計算”解決了效能瓶頸,另外一方面降低了硬體要求,這在網際網路 免費的時代,無疑對網際網路公司有著致命的誘惑力。也許我們很難清楚我們該部署怎樣的一個平臺,使用怎樣一種模式,但是當我們仔細的分析我們的現實情況、仔 細研究現有的成熟模式之後,一定會找到自己的理想的儲存平臺。