學習和實踐往往有很大的不同,而這些技巧也只有在企業中才可以學到。如果在工作的路上有高人指導,肯定會事半功倍。但大多數都沒有這樣的機遇,只好以夢為馬,以書為基,在程序員的道路上不斷披荊斬棘,克服困難,勇往直前。今天記錄一次公司的技術分享,讓我明白了,原來數據冗余也是一個利器。
數據庫范式
在上學學習數據庫的時候肯定都是要講到范式的,這里簡單回顧一下。
-第一范式(1NF)
所有的域都應該是原子性的,即數據庫表的每一列都是不可分割的原子數據項,而不能是集合,數組,記錄等非原子數據項,即沒有重復域。
-第二范式(2NF)
在滿足第一范式的基礎上,要求數據庫表中的每個實例或記錄必須可以被唯一地區分。
-第三范式(3NF)
在滿足第二范式的基礎上,任何非主屬性不依賴於其它非主屬性。
一定的冗余可以提升性能
冗余是指在一個數據集合中重復的數據稱為數據冗余。
1.空間換時間
有一張字典表 city 其中有 id 和 cityName 兩個字段,有一張業務表,其中有 id 、cityId、XXX、XXX…字段。
如果查詢業務表的話,就必須 join 一下 city 字典表,如果業務表很大很大,那么就會查詢的很慢,這個時候我們就可以使用冗余來解決這個問題,直接將業務表中的 cityId 更換成 cityName,這樣我們在查詢業務表的時候就不需要去 join 那一張 city 的字典表了。這樣的方式顯然是不符合我們數據庫設計的范式的,但是這樣的冗余或許很有必要。
2.查詢某一個狀態值數據
業務表中有一個字段 status 用來存儲提交和未提交,假設這張表中未提交的數據相對於提交的數據是很少的,當用戶查詢所有未提交的數據的時候,就需要在全部的數據,然后篩選出未同意的數據。如果這張業務表非常的龐大,那么這樣的查詢的效率就非常的慢。
這個時候我們就可以把這張業務表中的未同意的數據冗余到一張新表中,這樣用戶查詢未提交的數據的時候就可以直接在這張未提交的表中查詢,查詢速度提交很多。
3.拆分活躍數據和不活躍數據
某業務表有這樣的一個特點,用戶往往都在查詢最近三個月(或幾個月的)數據,數據每天都在增長,由於數據庫表的增長,查詢變得原來越慢,性能遇到瓶頸。這個時候可以根據業務將這張表拆分成三個月內數據和三個月外數據,其中三個月外數據還可以按照年份(或月份或季度)拆分成不同的分片。這樣用戶的查詢會大量的命中與三個月內的那張表中,而這張表的數據是有限的,並且數據量並不會特別大,從而解決性能的瓶頸。
4.匯總數據單獨存放
某業務表存放着每天的交易數據,用戶有的時候想查看某個季度,某一年份的交易總額。幾個用戶還好,當用戶量增加,查詢數增加,那么實時查詢的方法已經滿足不了要求,這個時候我們可以將這一類的匯總數據單獨的存放到一張表中,通過在夜間用戶量較少的時候計算出來,當用戶再次查詢的時候我們直接顯示這張匯總表中的數據,而不通過查詢交易數據表實時計算,這樣可以大量的提高性能。
在剛剛工作的時候我心里還抱怨說公司數據庫設計的一點都不好,大量的數據冗余,這么連第二范式都不符合呢?這里應該使用外鍵鏈接啊…現在才明白自己當時是多么的無知。最近一直在反思自己是不是太浮躁,在別人面前班門弄釜,或許真的應該“將肉扣在碗底吃”?好好鑽研技術,該說的就說,不該說的堅決不說。