學(xué)習(xí)數(shù)據(jù)庫的套路
【要不要學(xué) or 為什么要學(xué)】
很多學(xué)生在選一門課的時候,最基本的問題往往不會去關(guān)心。同時,學(xué)生們也沒有權(quán)利去選擇,畢竟有培養(yǎng)計劃這種東西。所以老師
要做的是激發(fā)起大家學(xué)習(xí)的欲望,這一點做的好,往往會水到渠成。
另一個是,你需不需要學(xué),是找別人幫忙,還是自己做?學(xué)習(xí)數(shù)據(jù)庫你要花費的時間成本是多少,如果我告訴你掌握數(shù)據(jù)庫需要十年,你當(dāng)然不干了。
我學(xué)習(xí)數(shù)據(jù)庫,是基于我做項目的需求。很簡單,我做Web開發(fā)需要存儲信息,總不能都靠非結(jié)構(gòu)式文件,而且各種查詢處理都不方便對吧。
【DBMS 的選擇】
于是搜索數(shù)據(jù)庫,哇好多種DBMS的種類,而且SQL 與 NoSQL 讓人眼花繚亂,看需求吧,首先目前做的項目是單個服務(wù)器的,所以不涉及分布式,而且是內(nèi)部訪問,并發(fā)不高,而且SQL相關(guān)的資料又很多,種種原因,選SQL好了,那么DBMS又有很多: MySQL , Oracle,SQL Server 等等,我選了MySQL,主要因為免費,而且DBMS的很多高級功能我暫時用不上,所以就它了。
有人會覺得,NoSQL出來了,而且這么火,關(guān)系型數(shù)據(jù)庫真LOW,這種東西早就應(yīng)該被淘汰了吧,(Sorry,我曾經(jīng)也屬于狂熱追求新技術(shù)的分子)實際上不然,阿里淘寶等國內(nèi)的大部分公司依然在用MySQL,無論從就業(yè)的角度或者是學(xué)習(xí)的角度,SQL的學(xué)習(xí)都是必要的,沒有一種完美的解決方案,SQL與NoSQL都有各自的短板,接下來的文章里我們再細(xì)談。
【項目需求分析】
首先目前我想做的是一個XX系統(tǒng)。
我這里且叫它課堂交互系統(tǒng)吧,對,就是花了一年都沒做出來的那個,心累。
在數(shù)據(jù)庫設(shè)計的第一步,我們要明確需求,就是說,這個課堂交互系統(tǒng)都有哪些功能點,例如:考試開啟一次小組互評,小組管理,學(xué)生之間的小組互評等等。(在軟件工程和產(chǎn)品經(jīng)理的課程里面有詳細(xì)的說明)
【概念模型設(shè)計】
我有了想做的功能,那下一步要做的是不是就是要分析,每個功能模塊中對應(yīng)的都有哪些"實體" ,實體之間的"聯(lián)系",以及實體本身都有哪些"屬性"。
但是自己在紙上亂涂亂畫,好混亂有沒有?所以我們需要借助E-R模型來幫助我們分析關(guān)系。
問題 1: 實體之間都有哪些關(guān)系呢,每種關(guān)系在E-R上都是如何去表示的。
當(dāng)我想存選擇測驗的時候
(1)一個測驗,可以有多個選擇題(好吧 ,主觀題/簡答題這里我們就先不說了),而一個選擇題又可能出現(xiàn)在多個測驗中,這叫多對多(Many-to-Many)
(2)一個試題對應(yīng)多個選項,而且選項不確定。那么好了,這是一對多的關(guān)系(單選還是多選,它們都一樣嗎?存儲的方式有啥不同)
(3)最日狗的地方來了,學(xué)生做題的記錄怎么存?
如上的這一系列的思考,并不是我在做哪套題目,而是我在做這個項目的時候,真真切切需要結(jié)局的問題。
問題 2:E-R 如何才能畫的好 ? (結(jié)構(gòu)清晰,分層)
當(dāng)學(xué)會畫E-R圖的時候,總是發(fā)現(xiàn)最后都畫成了一坨,而且一個項目的實體又那么多,彼此的關(guān)系錯綜復(fù)雜,最后各種跳線,畫出了你根本看不懂的E-R圖。
你想我都看不懂了,多大的問題??!
所以要學(xué)會分層,每個功能模塊分開畫,細(xì)節(jié)后述。
這是還可以上升到人生哲學(xué)的高度,從頂向下,逐層細(xì)分問題,各個擊破。完美!
【關(guān)系模型】
關(guān)系模型是數(shù)據(jù)模型的一種,因為我們這里要使用的是MySQL,所以我們需要采用關(guān)系模式進(jìn)行分析。
為啥要這樣干,因為你又不能通過E-R直接生成表結(jié)構(gòu)。所以你需要將E-R模型“翻譯”成關(guān)系結(jié)構(gòu)。
問題3 : 每種E-R中的關(guān)系,映射到關(guān)系模式中,方式是唯一的嗎?E-R圖有沒有一種設(shè)計規(guī)則來指導(dǎo)我們呢?他給定的設(shè)計規(guī)則我一定就要遵守嗎?
顯然不是嘛。
舉例來說E-R模型中的Is-a關(guān)系 即 繼承關(guān)系。舉例說明,老師和學(xué)生之間的關(guān)系,這里他們都是這個系統(tǒng)的用戶,老師和學(xué)生都可以評價小組展示的內(nèi)容,包括用戶的登陸,注冊等等功能模塊,老師跟學(xué)生是很類似的,最后設(shè)計出來的表結(jié)構(gòu),你會發(fā)現(xiàn)列的內(nèi)容只有很少的差別,這里我們將二者抽象成一個User 實體。
問題來了 :怎么存?
(1)這兩個我能都放在User表中,對一張表,那各有的字段怎么辦,比如學(xué)生有學(xué)號,老師有教工號咋整?冗余字段唄。User中同時有學(xué)號和教工號這兩列
(2)第二種是Student和Teacher各自一張表,分家了,自己存自己的。
(3)三張表,User,Student,Teacher,User中存取共同的部分,Student,Teacher存各自特有的部分
問題4: 在這里面哪種是最好的設(shè)計呢?
Sorry,這里沒有標(biāo)準(zhǔn)答案,這也是數(shù)據(jù)庫設(shè)計思想里面最吸引我的地方。
范式
雖然有范式(1NF,2NF,3NF,BCNF)的數(shù)據(jù)庫設(shè)計理論來消除冗余,但是不必較真,你設(shè)計的表結(jié)構(gòu)越分散,就意味著你寫查詢的時候會很麻煩,耗時也會越長,對大家的要求是,先能夠做到功能實現(xiàn)。武林高手的進(jìn)階大概會經(jīng)歷這么幾個階段:
沒有對錯,只有哪個更適合你此時的需求,對此事的,很可能你系統(tǒng)運行一個月之后會變得很卡,問題的答案又會變掉了。
同樣的,永遠(yuǎn)都沒有完美的數(shù)據(jù)庫設(shè)計,好的數(shù)據(jù)并不是一開始就設(shè)計好的,而是一次一次迭代出來的。(可能是需求變更,也可能是數(shù)據(jù)庫設(shè)計的優(yōu)化)
這里推薦一本書《SQL反模式》。
給老師的建議
其實,設(shè)計一個數(shù)據(jù)庫是最簡單的,這里我先不說好壞,起碼你功能實現(xiàn)了。但是在實際的應(yīng)用中,我覺得是遠(yuǎn)遠(yuǎn)不夠的。如何測試一個數(shù)據(jù)設(shè)計的好壞,能不能提供大量的數(shù)據(jù)存入,然后模擬高并發(fā)的訪問,測試一個數(shù)據(jù)庫的設(shè)計的好壞?
當(dāng)學(xué)生寫的一個SQL查詢需要執(zhí)行一天的話,那么,絕對出了問題。 是你數(shù)據(jù)庫設(shè)計的問題 (例如:沒做好索引)?還是SQL語句的書寫需要優(yōu)化?
【物理模型設(shè)計】
現(xiàn)在你有了關(guān)系模型,感覺它離著變成數(shù)據(jù)庫中真實的表似乎指日可待了對吧。
別急。。。
(1) 字段屬性
還記得你的在數(shù)據(jù)庫的概念設(shè)計里面實體有很多屬性對吧,例如
學(xué)生(學(xué)號,學(xué)生姓名,年齡,學(xué)院ID,專業(yè),注冊時間)
屬性有了,每個數(shù)據(jù)采用哪些數(shù)據(jù)類型呢?你需要了解MySQL中都有哪些數(shù)據(jù)類型,相似的數(shù)據(jù)類型區(qū)別是啥?
(2) 各種約束
實體完整性,根據(jù)某幾個字段,定位某個特性的行。這個當(dāng)然不能呢為空啦,要不你都找不到它了。
參照完整性,例如學(xué)生實體的學(xué)院ID,學(xué)院ID是外碼,如果學(xué)院ID沒有或者對應(yīng)的學(xué)院ID在學(xué)院表中不存在,什么鬼,你不屬于任何一個學(xué)院,那你不是很無助。
用戶自定義完整性
簡單來說除了上面的兩種,其他的用戶定義的約束,都屬于用戶自定義約束。
學(xué)生實體中有一個屬性是 年齡。
好,年齡對吧,-1歲,顯然不行,今年是2016年你2017年出生了這也太玄幻了,穿越了?,1000歲?能活到這個歲數(shù)的應(yīng)該是王八吧。
所以我需要給年齡設(shè)定一個年齡范圍例如 0- 110
超出這個字段的,我都定義為非法。
【創(chuàng)建表結(jié)構(gòu)】
現(xiàn)在你需要學(xué)些SQL了,開始的時候你需要創(chuàng)建一個數(shù)據(jù)庫,在數(shù)據(jù)庫中定義表,定義視圖,這種操作都叫DDL(Database Define Language ),對應(yīng)的你需要用DDL寫出Create Table的相應(yīng)的SQL語句。
【SQL基本操作】
表結(jié)構(gòu)有了,但是你還沒有數(shù)據(jù),插插插,將數(shù)據(jù)Insert進(jìn)你的表中。
我還需要查詢表(Select),刪除(Delete)一條數(shù)據(jù),更新(Update)一條記錄。
【加特效 :數(shù)據(jù)庫程序設(shè)計】
視圖
觸發(fā)器
存儲結(jié)構(gòu)
Note: 暫時先寫到這里,工程經(jīng)驗止于此,不愿意誤人子弟。
心靈硫酸
老師的職責(zé)
(1) 往那走
給學(xué)生方向上的指引,用哪個DBMS,學(xué)習(xí)方式,學(xué)習(xí)資源。
(2) 喂,走偏了
點到為止
老師教的越多,學(xué)生能夠接收的信息也就越少。
克制住,先別告訴他原則,讓他們違背,走到坑里,很痛苦,記憶也就更深刻,這樣才會有需求。
我們總是被告知,不要這樣,要那樣!可是為啥呢,我們并沒有很深層次的感悟,內(nèi)心無感。
在合適的地方,合適的時間,合適的地點,給與適當(dāng)?shù)闹敢?br>
溫柔的告訴他:“也許你應(yīng)該看一下課本上XX的部分,可能會對你有寫幫助”。
不貪
不要意味的看各種設(shè)計指導(dǎo)原則,不要貪多,想掌握全部的SQL,更多的還是根據(jù)自己的需求來吧,你需要用到哪些功能,不夠再學(xué)嗎,循序漸進(jìn)。
學(xué)習(xí) = 學(xué) + 習(xí),練習(xí)實踐很重要。
你學(xué)習(xí)的內(nèi)容,能不能轉(zhuǎn)換成生產(chǎn)力,等于你是否在有效學(xué)習(xí)。
項目導(dǎo)向
項目進(jìn)行中遇到問題了,有了需求,然后去找解決方案。
不燥
文章前面有提到,不要盲目的追求新技術(shù)
接受不完美,并且努力做得更好
給項目管理人員:PDCA理論
PDCA來自于戶外拓展理論,同理它也可以放在數(shù)據(jù)庫設(shè)計的過程中。
Plan 計劃
做計劃,一開始就動手做,往往需要頻繁的返工。
指定適當(dāng)?shù)挠媱潱纸馊蝿?wù),逐層分解。
Do 嘗試
總計劃,不去嘗試,等于0。
一開始,計劃絕對是不靠譜的,而且項目管理者往往會時間估計的比較樂觀,比如我。
所以要去試錯,做一個Demo,去驗證項目計劃的可行性。
Change
在我們不斷的嘗試的過程中,發(fā)現(xiàn)了計劃中很多不合理的地方,咋辦,改計劃唄。
循環(huán)往復(fù)執(zhí)行,直到計劃靠譜。
Action
不要慫,開始動手做吧。