需求分析及逻辑设计
首先按照數據庫設計的步驟呢,我們先來看一看需求說明,我們的主要設計呢,是一個電子商務網站,相關的設計說明呢,是這樣的,按下面的需求設計一個電子商務網站的數據庫結構,首先第一點呢,是本網站只銷售圖書類的商品,其次這個網站需要具有以下的功能,如用戶登錄啊,用戶管理啊,商品展示,商品管理,供應商管理以及在線銷售功能,雖然項目的說明是很簡單的,但是如果我們對上面的需求進行分析,可以發現,我們所要面對的工作呢,并不像表面上想的那么簡單,按照數據庫設計的步驟,我們要對下面的需求進行詳細的分析,在真實的環境中呢,我們的需求分析是需要和需求提出的人反復的溝通的,可以把這個需求確定下來,但是這里我們就不會這么麻煩了,我們只需要自己對著需求進行分析就可以了,實際上我們就是這個需求的分析和提出人
那么我現在來看一看,如何進行需求分析以及邏輯設計,我們首先來看看用戶登錄和管理功能需要注意寫什么問題,首先來說,第一點是用戶必須進行注冊,登陸后才能在網上交易,這里要我們能夠通過唯一的標識來標識出每一個用戶,這個唯一的標識呢,也就是我們前面所提到的業務主鍵,在這里我們選擇使用用戶名來作為用戶信息的業務主鍵,同時這就要求我們在系統中用戶名呢必須去保持唯一的
第二點就是為了保證用戶的安全性呢,我們的系統要求,同一個時間呢,同一個用戶,只能在同一個地點來進行登陸,這個對我們數據庫設計的影響呢,要求我們在進行用戶表的設計中呢,記錄用戶是否登陸的狀態信息,另外我們還要求用戶在注冊時呢,必須提供一些信息,這些信息也會存入到我們的用戶表中,下面就是用戶信息表的一些屬性,首先紅色標識的用戶名呢,就是我們前面說的業務主鍵,而密碼和手機號呢,也是用戶首先必須要提供的,真實姓名和出生日期是兩個可選的屬性,而注冊日期和在線狀態呢,是由我們系統來維護的兩個屬性,當然真實的這種網站呢,用戶信息表的屬性呢,要多的多,我們舉個例子來說呢,以上這些信息就已經足夠了,接下來我們再來看看這個用戶信息表的邏輯事務中是否符合我們數據庫設計的范式呢
由于這個表中只有一個業務主鍵,所以一定是符合第二范式要求的,另外也沒有屬性和我們的業務主鍵呢,存在傳遞依賴的關系,所以也是符合第三范式的要求,現在看來呢,我們用戶信息表的邏輯設計已經完成了,下面我們要來看看其他的業務模塊
那么我們就來看看商品展示模塊,商品展示模塊呢,主要用于前臺瀏覽商品信息,和后臺管理編輯商品信息,和相關的一些模塊,前面需求中,提到了我們這個網站呢,實際上只銷售一種商品,實際上是圖書,這個信息對于我們設計商品,非常的有用,這就決定了我們商品信息表中商品信息呢,只要記錄圖書的一些商品信息就可以了,另外呢除了商品信息外呢,還要記錄商品分類,和商品供應商相關的信息,下面就是我們列子中商品模塊中所要記錄的一些信息,大家可以看到,包括商品名稱,分類名稱,供應商名稱,出版社名稱,圖書的價格,圖書的描述,作者等等,由于一本書還可以分屬于多個分類,所以商品名稱和分類兩個屬性能夠作為我們的業務主鍵,才能唯一的確認一本書,當然在真實的環境中,所需要要記錄的信息呢,遠遠比上面的要多得多,如果上面的信息我們放在一個表中,也會出現那個問題,首先這樣的設計一定是不符合三大范式的要求,比如分類信息在這張表中就存在數據維護異常的,如果我們新增加一個分類,在這個分類中還沒有相關的圖書的話,那么這個分類呢,就無法進行記錄,所以我們要對這張表進行拆分,使其滿足數據庫范式的要求,下面就是拆分后商品模塊的相關屬性信息,我們把商品信息表拆分為商品信息表,商品分類以及商品分類對應關系三張表,其中商品信息表中的屬性呢,包括商品名稱,出版社名稱,圖書價格,還有圖書的描述,作者,其中圖書名稱就是我們的業務主鍵,而分類信息表中的主鍵呢,則有分類名稱,和分類描述,其中分類名稱作為分類表中的主鍵,最后是一個商品和分類的對應關系表,這個表中只有兩個屬性,就是圖書的名稱和分類的名稱,并且這個表中的兩個屬性呢,成為了一個聯合的業務屬性,以上就是拆分后的三張表,這三張表已經符合三大范式的要求,并且我們可以看到,這三張表中呢,存在數據冗余啊,以及數據維護異常的問題,這樣我們就完成商品模塊的設計,接下來我們來看看電商模塊
電商模塊是用于記錄供應商模塊信息的,在我們的例子中呢,也就是出版社的信息,在供應商模塊中,來看一下,在這個模塊中呢,可能會記錄一下的一些屬性,首先對于供應商信息,我們例子中只需要出版社的名稱,地址,電話,聯系人,銀行賬號這樣的信息就足夠了,同時呢我們以出版社名稱來作為供應商信息表的業務主鍵,由于這個表只有一個主鍵,同時也不存在非主鍵對主鍵的這種部分依賴的關系,所以我們可以把這些信息全部存在供應商這些表中,這樣就已經符合我們的第三范式要求了,下面我們來看一下我們最后一個模塊,也是最主要的一個模塊,在線銷售模塊的設計,在線銷售模塊呢,是電商網站的一個核心模塊,我們所做的一切工作呢都是為了把我們網站的商品銷售出去,所以在線銷售模塊呢,遇到的內容也會非常的多,以我們的例子來說,至少要包括以下的屬性,首先訂單編號,下單用戶名,下單日期,訂單的金額,訂單的商品分類,訂單商品名,訂單商品的單價,訂單商品數量,支付金額以及物流單號,那這些屬性中呢,可以使用訂單編號來作為主鍵,由于在這里只有一個業務主鍵,所以是符合第二范式的,但是不難發現,在這些屬性中呢,訂單商品的單價,訂單商品的數量和訂單編號,之間是存在傳遞依賴關系的,如果我們把這些信息放在一張表中,顯然是不符合第三范式要求的,同時這張表還會存在數據冗余的問題,所有的訂單商品信息呢,和商品信息表中的商品信息呢,都是冗余的,所以我們要對這些表進行拆分,使其符合第三范式的要求
首先我們把在線銷售這個實體呢,拆分成一個訂單表,其中包括訂單編號,下單用戶名,下單日期,和物流單號這些屬性,大家注意這里并沒有物流價格,這也是因為物流價格我們可以通過商品單價乘以商品數量的方式來計算得出,所以嚴格來說呢,也是一個冗余數據,另外還拆分了一個訂單商品關聯表,其中包括訂單編號,訂單分類,以及商品名,商品數量等屬性,大家可以看到,在這幾個屬性里面呢,訂單編號是訂單表的主鍵,而商品分類和商品名,商品分類關聯表的主鍵,而唯一非主鍵屬性呢,商品數量,也和主鍵不存在傳遞依賴的關系,所以這樣拆分之后呢,兩張表就變成了符合范式要求的表,這樣就完成了我們演示系統數據庫的邏輯設計,但是大家可以想象一下,這樣的設計雖然是符合了范式化的要求,但是對于數據庫處理來說,是否就是高效的呢,前面我們說過,進行數據庫設計時,不僅要考慮范式化設計的要求,同時還要考慮查詢性能的要求,假設我們的業務中需要進行以下的查詢,我們來看一看,這個SQL語句要如何來寫
假設我們現在想查詢出,用戶訂單總金額,那么我們SQL要如何寫呢,下面就是SQL的樣子,首先這個SQL一共關聯四張表,從前面的內容大家可以知道,對于MYSQL來說呢,關聯的表越多呢,性能就越差,雖然四張表并不太多,但是由于這樣的查詢會非常的頻繁,所以如果可以減少關聯表的數量呢,可以對數據庫性能起到不少的優化作用,另外再請大家考慮一個問題,如果我們的商品價格變動了的話,會出現什么樣的情況,因為現在只在商品表中記錄了商品的價格,所以一旦商品的價格發生了變化,那么我們的程序結果也發生了變化,這是所有人不想看到的結果,我們總是希望查詢我們的歷史訂單的時候呢,可以碰到當時購買的價格,而不是現在的價格,所以呢,從業務的角度來看呢,設計呢雖然是完全符合范式化表的要求,但是可能還是存在問題的
我們下面再來看另外一個場景,我們現在要考慮以下問題,我們假設下單用戶就是商品的收貨人,所以我們在進行發貨前呢,一定要查詢出每個訂單的下單人的信息,而這些信息呢,全部記錄在用戶信息表中
這樣的話呢,如果想要查詢出我們需要的信息呢,那么我們就必須使用下面的SQL來寫,大家看到呢,這個SQL呢要比之前的SQL呢,還要在多關聯一張表,那就是用戶信息表,而且要在這些信息中呢,增加訂單總額,信息的話,那么這個SQL寫起來就會更加的復雜,效率也會更低,而我們所舉的兩個SQL呢,都是我們系統中經常要查詢的SQL,所以這樣看來呢,完全符合范式化的表結構呢,并不能得到良好的SQL查詢性能,所以我們要根據我們的業務中的所使用的SQL查詢呢,來對以上的邏輯設計呢,進行一些優化,要進行一些反范式化的設計,下面我們就來看如何對這些表進行反范式化設計
要對數據庫進行反范式化設計,先要了解什么是反范式化,反范式化實際上是針對范式化而言的,我們在前面介紹了數據庫設計的幾種范式,那么在范式化的數據庫中,每個數據會僅會出現一次,那么所謂的反范式化呢,是為了提高數據庫的查詢性能,和讀取效率,考慮而適當的對數據庫設計范式的要求進行違反,同時允許存在少量的數據冗余,換句話來說呢,反范式化的目的呢,使用我們的存儲空間,來換取更少的時間,那么這樣什么是反范式化,我們就可以著手對我們之前設計的,完全符合范式化邏輯結構來進行反范式化設計了
適當的增加一些數據冗余,以獲得更好的查詢性能,下面是需要進行反范式化設計的表,首先我們先來看看,商品信息表來進行反范式化設計,之前我們所設計的商品信息表是這樣的,三張表,商品信息表,分類信息表,以及商品分類關系表,那么從剛才的查詢中呢,可以看到,如果要查詢出一個商品的信息,我們必須要關聯出這三張表,而商品分類和商品名稱這兩列呢,由于標識了一個具體的分類,所以幾乎每次查詢呢,都要重復用到,所以我們對商品信息表進行反范式化呢,就會增加分類名稱這一列,現在在商品信息表中呢,包含了商品名稱和分類名稱,這樣處理以后呢,商品信息表中增加了一些冗余數據,為了避免操作異常呢,同時還會暴露分類信息表,這樣對于新增的無圖書分類呢,可以在分類信息表中進行記錄,所以也就不會造成丟失信息分類的這種情況,這樣我們就完成了商品信息表,相關的反范式化設計,大家可以看到,這時呢,如果我們想要查詢商品信息的話,我們只需要從商品信息表中就可以得到了,減少了兩個表的關聯
下面我們來看看根據之前的查詢,所看出來的另一個需要做反范式化優化的表,也就是銷售相關的一些表,原本呢我們按照范式化的設計呢,訂單表是如下的,包括訂單表和訂單商品關聯表,之前我們在寫查詢語句的時候呢,發現,和訂單表一起查詢的用戶的相關信息呢,用戶名,另一個就是用戶下單的手機號,原來的表設計呢,如果想要獲取用戶名和其對應的手機號呢,就必須要關聯用戶表,來進行查詢,一旦用戶在維護信息中,改變了手機號,訂單信息的手機號也就會發生變化,這在業務上也是不允許的,因為不可能我們下單時寫手機號,而我們配送時又是另一個手機號,我們很難聯系到買這個的人,我們就要把我們用戶的手機號記錄到我們的訂單表中,另一個增加到訂單表中的列呢,就是訂單金額列,這一列也是經常會被查詢到的,原來我們是需要通過訂單商品關聯表和訂單表中的信息呢,才能計算這一列的值,而如果訂單表中的信息如果發生變動,我們的訂單金額也會隨之變動,所以為了避免這種情況的發生呢,我們把這一列呢在訂單表中也進行了冗余,那么反范式化后的訂單表呢,就變成了現在的這種結構,包括了訂單編號,下單用戶名,手機號,以及訂單的金額這些信息,我們再來看一下訂單商品關系表,由于之前說的,商品信息表中的商品價格變動呢,同樣也會對我們的商品訂單商品關聯表中的信息進行影響,所以我們在訂單商品關聯表中呢,同樣冗余了單價,這樣訂單商品關聯表呢,就變成了這種結構,我們把商品單價在在訂單商品關聯表中進行了冗余,我們上面對表進行了反范式化的優化,優化之后呢,我們對剛才所提出的需求來進行一些處理
看一下現在的SQL語句變成了什么樣子,同樣我們還是來看一下反范式化后,查詢出每一個用戶訂單總金額的需求變成什么樣子了,由于我們已經把訂單金額,在訂單表中進行了冗余,這個查詢就變得非常的簡單,大家可以看到,現在我們只要對一個表進行匯總操作,就可以拿到之前關聯四張表才能達到的目的,這樣就大大提高SQL的執行效率,可見呢,我們的反范式化優化呢,是十分有效地,下面我們再來看看另外一個查詢需求的情況
編寫SQL查詢出下單用戶和訂單詳情信息,那么這個SQL呢,之前我們關聯了5張表才能夠實現,而現在我們對訂單表,和訂單商品表的關聯呢,已經商品信息表進行反范式化操作之后,在進行同樣的查詢呢,MYSQL就會變得非常的簡單,由于我們對于用戶的手機號,商品價格的訂單表和訂單商品表中呢,進行了冗余處理,所以現在的SQL就變成了現在這個樣子,這個SQL就是經過反范式化處理以后的查詢的SQL,和之前的商品經過反范式化處理以后的SQL呢,同樣變得高效了很多,可見我們在進行數據庫設計時呢,并不能完全的按照范式化的要求來進行設計
同時還必須要考慮我們以后要如何使用這些表,而在范式化設計基礎之上呢,根據應用中查詢的SQL呢,表設計要進行反范式化的優化,這樣可以設計出最符合性能和業務要求的數據庫的結構,從上面的例子中呢,我們可以看出,數據庫的設計呢,對數據庫性能確實是有很大的影響,以上面的兩個SQL為例,如果我們的設計呢,是完全按照范式化設計來進行的,那么無論后期如何對SQL進行優化呢,都達不到對數據庫結構進行反范式化之后的查詢效率,不過完全的反范式化設計呢,也行不通的,因為那樣會造成大量的數據冗余,和數據的維護異常,下面我們來總結一下,范式化設計和反范式化設計的優缺點,這樣大家在進行數據庫設計時呢,就知道如何選擇對表進行范式化設計和反范式化設計了
?
總結
- 上一篇: 数据库结构优化介绍
- 下一篇: 范式化设计和反范式化设计优缺点