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