隨著工作經(jīng)驗的積累,我日益感覺到,對一名程序員來說,擁有良好的數(shù)據(jù)庫設(shè)計能力是很重要的,甚至是最重要的。
程序員界有一句著名的話
Talk is cheap, show me the code
把這句話演變一下,就成了
Code is boring, show me the data structure
數(shù)據(jù)庫的種類很多,對于像作者這樣的web后端程序員來說,可以把范圍縮小到關(guān)系型數(shù)據(jù)庫、非關(guān)系型數(shù)據(jù)庫與NoSQL數(shù)據(jù)庫。
數(shù)據(jù)結(jié)構(gòu)為何如此重要
一切代碼都是圍繞數(shù)據(jù)結(jié)構(gòu)運行的。
客戶端展現(xiàn)的動態(tài)數(shù)據(jù),都是存儲在數(shù)據(jù)庫中,這對程序員來說一定是常識了。拿你正在瀏覽的這個頁面為例,文章的作者、標(biāo)題、正文、評論、喜歡等等,只要你打開任意兩篇文章,兩個頁面不一樣的地方,幾乎都是因為在數(shù)據(jù)庫中存儲的內(nèi)容不同。
良好的數(shù)據(jù)結(jié)構(gòu)可以提升性能,使代碼變得簡單、清晰。數(shù)據(jù)結(jié)構(gòu)清晰了,圍繞著數(shù)據(jù)運行的代碼自然就清晰了。
數(shù)據(jù)庫設(shè)計需考慮的因素
提到數(shù)據(jù)庫設(shè)計原則,首先會想到第一、第二、第三范式,這些理論能了解最好,但這不是本文探討的主題。
面對一個具體的應(yīng)用場景,設(shè)計數(shù)據(jù)庫時應(yīng)考慮哪些因素?為了能夠言之有物,我們拿簡書的文章頁面來現(xiàn)身說法。
當(dāng)前可用性
數(shù)據(jù)結(jié)構(gòu)的設(shè)計要能達到應(yīng)用場景的要求,這是最基本的。舉個例子,這篇文章的正文存儲在了數(shù)據(jù)表中的某個字段,該字段的長度被設(shè)定為1000字,這顯然不能滿足應(yīng)用場景的要求,文章寫到這里已經(jīng)超過了1000字(估計的,我沒有數(shù))。
適當(dāng)超前
超前到什么程度需要根據(jù)對應(yīng)用的預(yù)期來定。拿QQ來說,馬化騰最初肯定預(yù)見不到QQ能有目前的用戶量與活躍度,畢竟那是近20年前的事情了。
對于本文設(shè)定的應(yīng)用場景,我們把超前設(shè)定為網(wǎng)站的文章數(shù)量達到了千萬級。這時如果只把文章存在一張數(shù)據(jù)表里,讀寫性能必然是會急劇下降的,這必然會導(dǎo)致用戶體驗變差,用戶流失。老板不能容忍,DBA也不能容忍。
合理的解決方案之一是分為兩張數(shù)據(jù)表,一張存儲熱門文章,另一張存儲非熱門文章。畢竟熱門文章占少數(shù),熱門文章的加載速度相對就更快了。還有別的解決方案嗎?肯定有,留給您自己思考。
分離易變與不易變部分
對于一篇文章來說,哪些是易變的,哪些是不易變(不變)的?
不易變(不變)
作者
標(biāo)題
正文(字數(shù))
發(fā)布時間
更新時間
易變
閱讀次數(shù)
評論
喜歡該文章的用戶與數(shù)量
拆分的好處在于,首先數(shù)據(jù)結(jié)構(gòu)更清晰了,其次可以提高讀寫性能,當(dāng)文章有了新評論,只需更新存放評論的數(shù)據(jù)表。如果不拆分,需要更新的記錄占用的磁盤空間很大,這對磁盤IO速度是個考驗。
對于拆分出的部分,可以繼續(xù)運用這些原則進行設(shè)計。
應(yīng)對可能出現(xiàn)的新需求
互聯(lián)網(wǎng)應(yīng)用的迭代周期很短,設(shè)計數(shù)據(jù)結(jié)構(gòu)時應(yīng)考慮到可能出現(xiàn)的新需求。拿喜歡該文章的用戶與數(shù)量舉例。
為了達到應(yīng)用的要求,最簡單的方式是將這些用戶放在一條記錄里,存儲的字段可以是數(shù)組類型。這樣設(shè)計,喜歡文章的用戶信息與用戶數(shù)量都能輕易獲取,讀寫性能也很好。
某天,產(chǎn)品經(jīng)理找到了你:“商量個新需求唄”,在文章下方加個模塊,就叫“喜歡該文章的人還喜歡了”。你就懵逼了,沒法破,除非重新設(shè)計數(shù)據(jù)結(jié)構(gòu),然后就帶來了遷移數(shù)據(jù)一系列事情。其實這個需求挺合理的,說得高大上一點,這叫“精準(zhǔn)推薦”。
很明顯,將用戶放在數(shù)組里只能支持“查詢喜歡某文章的用戶”,不支持“查詢某用戶喜歡的文章”。
適當(dāng)?shù)娜哂?/p>
或許你已經(jīng)注意到了,文章的標(biāo)題下面有這篇文章的字數(shù)。計算文章的字數(shù),有兩個時機:
保存文章時
讀取文章時
后者的優(yōu)勢在于數(shù)據(jù)表中少了一個字段,而且這個字段不是必需的。哪個時機更好?個人覺得前者更好,理由如下:
計算長篇文章的字數(shù)是比較耗時的,應(yīng)盡量減少計算次數(shù)
總體來看,文章的保存次數(shù)遠小于讀取次數(shù)
如果能夠提高應(yīng)用的性能,適當(dāng)?shù)娜哂嗍潜匾摹?/p>
結(jié)尾
本文總結(jié)了設(shè)計數(shù)據(jù)庫時需遵守的幾個原則
可用性
適當(dāng)超前
應(yīng)對新需求
分離易變與不易變部分
適當(dāng)冗余
因為自知還未達到數(shù)據(jù)庫專家的水準(zhǔn),寫出的內(nèi)容肯定有不準(zhǔn)確的地方,歡迎批評指正。
寫這篇文章的想法醞釀很久了,但一直沒時間動筆。適逢中秋佳節(jié),上海下著大雨,不便出門行走,便安坐在電腦前敲下了這千八百字,前后花了兩個多小時。如果喜歡就點贊,能指出不足或提出意見就更好了。