不要隨意使用mongoDB

作者:挨踢直男
原文:http://suo.im/6xYQqy
mongodb是一種非關(guān)系數(shù)據(jù)庫,最常見的作用是在某些領(lǐng)域作為關(guān)系數(shù)據(jù)庫的替代品,相較于關(guān)系數(shù)據(jù)庫它在性能上更有優(yōu)勢,因為不對事務(wù)以及數(shù)據(jù)完整性有硬性要求,所以在寫入數(shù)據(jù)時效率更高。同時,mongdb的數(shù)據(jù)存儲結(jié)構(gòu)也比較靈活,只要是一個json結(jié)構(gòu)就可以存儲,相較于關(guān)系數(shù)據(jù)庫的表結(jié)構(gòu)定義,更加快捷方便。因為這些優(yōu)勢,mongodb迅速崛起,不斷蠶食關(guān)系數(shù)據(jù)庫從上個世紀(jì)就開始積累的市場份額。
關(guān)系數(shù)據(jù)庫存儲數(shù)據(jù)很規(guī)則,必須是表格的形式,且表格的結(jié)構(gòu)需要事先定義好,每個字段的數(shù)據(jù)類型、長度需要明確,這樣做的好處是表內(nèi)的一切都井井有條、很清晰,壞處就是很繁瑣。
而mongodb則相反,它對集合的結(jié)構(gòu)沒有統(tǒng)一的要求,任何結(jié)構(gòu)的文檔數(shù)據(jù)都可以寫入同一個集合,在一個集合里,既可以寫入用戶數(shù)據(jù),也可以寫入訂單數(shù)據(jù),mongodb本身不做任何限制,一切約束全靠程序員自身。
mongodb的這種隨意性是把雙刃劍,能帶來高效,也能造成災(zāi)難。尤其當(dāng)項目涉及的開發(fā)人員越多,需求變化越頻繁,mongodb存儲的數(shù)據(jù)就越容易變成一個屎坑,你無法完全知道某一個集合中的文檔哪些字段是有用的,哪些字段是沒用的,你的程序不得不去配合這些未知的數(shù)據(jù),從而造成不必要的繁瑣,以及帶來更多的BUG。
曾經(jīng)經(jīng)歷過一個項目,數(shù)據(jù)庫采用的是mongodb,在我接手時這個項目已經(jīng)開發(fā)運營了三年。那時,我需要理清楚某一個功能運行邏輯,最好的方法自然是先弄清楚功能相關(guān)聯(lián)的數(shù)據(jù)結(jié)構(gòu),于是我找到了那個功能依賴的mongodb集合,查看集合文檔的結(jié)構(gòu)。了解了文檔結(jié)構(gòu)之后,我修改了程序,完成了任務(wù)。然而修改后的功能總過會在某種情況下觸發(fā)一個BUG,經(jīng)過排查后發(fā)現(xiàn),我之前看到的數(shù)據(jù)結(jié)構(gòu)并不全面,在集合中某一批文檔中還有別的字段被程序所依賴,找到問題后我修好了BUG。然而在之后某些情況下程序仍舊會出現(xiàn)BUG,排查后找到的原因也是類似之前,總之這種狀態(tài)周而復(fù)始了好久才徹底修完了BUG。這就是之前的程序員對mongodb對數(shù)據(jù)結(jié)構(gòu)約束性不強(qiáng)這以特性濫用的結(jié)果。如果是關(guān)系數(shù)據(jù)庫,查看表結(jié)構(gòu)就能清楚所有的數(shù)據(jù)字段,很多BUG也就可以提前避免。
要寫出健壯且易于理解的程序,數(shù)據(jù)的存取必須是有模式的,比如關(guān)系數(shù)據(jù)庫的表結(jié)構(gòu)。然而關(guān)系數(shù)據(jù)庫太過于死板,只能存儲二維的表數(shù)據(jù)結(jié)構(gòu),雖然現(xiàn)代的關(guān)系數(shù)據(jù)庫對json和xml做了很好的支持,但是并沒有被廣泛使用,大多數(shù)時候只是使用基本的表功能。要兼顧靈活性和健壯性兩種優(yōu)點,那么我們只能引入外部模式。
有兩種結(jié)構(gòu)化數(shù)據(jù)協(xié)議很流行,一種是google開發(fā)的protobuf協(xié)議,一種是facebook開發(fā)的apache thrift協(xié)議。這兩種技術(shù)功能很強(qiáng)大,應(yīng)用范圍也很廣,要講清楚需要花費非常巨大的篇幅,讀者可自行去網(wǎng)上了解。

這兩種協(xié)議有一個核心的功能就是數(shù)據(jù)結(jié)構(gòu)的描述,以可以直接寫入mongodb的JSON以及php語言為例,有一個php數(shù)組,里面是需要存到數(shù)據(jù)庫里的數(shù)據(jù),我們將這個數(shù)組轉(zhuǎn)換成JSON ,然后存入mongodb,這一步一般是mongodb提供的驅(qū)動庫完成,這種方式我們很難約束數(shù)組的內(nèi)容,自然的也難以約束轉(zhuǎn)化成存入mongodb中JSON的內(nèi)容,從而導(dǎo)致最終的失控。使用這兩種技術(shù)之后,一切變得可控了,數(shù)據(jù)協(xié)議會生成對應(yīng)語言的類結(jié)構(gòu),然后通過他們內(nèi)置的庫序列化成JSON并存入mongodb。反過來,程序讀取是mongodb中的json,反序列化成語言的類結(jié)構(gòu)供程序使用,字段的語義說明則都由協(xié)議定義接管。
總而言之,mongodb不建議像關(guān)系數(shù)據(jù)庫那樣獨立使用,必須引入外部的模式定義,才能發(fā)揮作用同時避免副作用。

好文章,我在看
好文章,我在看
