CouchDB 讓人頭痛的十大問題
下面十條內(nèi)容來自paperplanes的博主Mathias Meyer,他也是一位NoSQL的實踐者,CouchDB就是其鐘愛的數(shù)據(jù)庫之一。正所謂愛之深恨之切,在使用CouchDB的過程中,他發(fā)現(xiàn)很多不順手的地方,就是本文列舉的十大問題。
View是在讀時更新的
我們知道CouchDB不支持動態(tài)查詢,也就是說你的每個查詢,都需要事先創(chuàng)建一個對應(yīng)的View,創(chuàng)建View是很快的,即使你的數(shù)據(jù)集很大,這 是因為CouchDB并不在創(chuàng)建View的時候就建立View索引,而是在讀取的時候來做這個事。當(dāng)在一個View上執(zhí)行一次讀操作時,CouchDB會 對比當(dāng)前View中的索引更新時間與最后寫操作時間,如果發(fā)現(xiàn)在索引更新之后又有寫操作,那么會把這段時間的寫操作合并到索引中再返回給客戶端。
你可以想象到,如果數(shù)據(jù)集非常大,你創(chuàng)建完View后的第一次讀取會是多慢。同樣的,如果你兩次讀操作間隔期間有太多的寫操作,那么也會導(dǎo)致讀操作 非常慢,有的朋友通過cron任務(wù)定時對View進行查詢,從而觸發(fā)定時的索引更新操作,以減少真正讀操作需要等待的時間,不得不說這真是蛋疼。這一切, 都是因為CouchDB的View是在讀時更新導(dǎo)致的。
而實際上,如果你不愿意等待CouchDB去更新完索引后再返回數(shù)據(jù),你也可以通過stale=ok參數(shù)指定它返回老數(shù)據(jù)即可,不用做更新操作。但 我們不能總是訪問老數(shù)據(jù),作者希望可以通過指定查詢先返回老的數(shù)據(jù),再進行相應(yīng)的索引更新操作。而實際上這一功能已經(jīng)在1.1.0版本中實現(xiàn)了,在 1.1.0版本中,添加了一個stale=update_after的指定,可以實現(xiàn)返回老數(shù)據(jù)后再在后臺更新的功能。
缺乏自動壓縮功能
CouchDB采用了append-only的方法進行數(shù)據(jù)更新,也就是所有數(shù)據(jù)的寫操作,都不會修改原來的數(shù)據(jù)文件,而是追加上新的版本來實現(xiàn)。 這使得CouchDB能夠?qū)崿F(xiàn)對同一條數(shù)據(jù)保存多個版本。也使得CouchDB的數(shù)據(jù)文件永遠(yuǎn)不會被改花掉。因為它永遠(yuǎn)在做append操作,即使出現(xiàn)問 題,只要去掉尾巴上一某一段數(shù)據(jù)就能回到之前某個時間的數(shù)據(jù)快照。
然而,這些好的特性必然需要付出代價,這代價就是數(shù)據(jù)大小會只增不減的膨脹。所以,數(shù)據(jù)壓縮工作是遲早都得做的事。但是CouchDB并沒有提供數(shù)據(jù)自動壓縮的功能。這讓人很郁悶。
不支持局部更新
局部更新的意思就是,不更新整條數(shù)據(jù),只更新其它某個屬性或字段。這個看似天經(jīng)地義的功能,在CouchDB里卻沒有。在CouchDB中,所有的update操作都需要對整條數(shù)據(jù)進行更新。
缺乏內(nèi)存的擴展性支持
CouchDB的同步機制是很牛X的,這幾乎是它的殺手級功能。你可以隨意在集群中添加刪除節(jié)點, 可以隨意指定Master和Slave的角色, 數(shù)據(jù)都會很好的同步到所有節(jié)點上。能達(dá)到這樣的效果,是由CouchDB本身的機制決定的。然而,我們并不能做跨節(jié)點的讀寫操作。
在這方面,CouchDB-lounge算是一個嘗試,但是它把整個架構(gòu)復(fù)雜化了,我感覺不太舒服。
分頁實現(xiàn)起來會很奇怪
如果你要對CouchDB中的數(shù)據(jù)進行分頁展示,這會比較麻煩,在《CouchDB權(quán)威指南》中有一個對分頁的實現(xiàn),但是這個實現(xiàn)給人感覺非常別扭。如果你要在CouchDB中實現(xiàn)分頁的話,最好還是用那個“獲取更多”按鈕的方式來做。
范圍查詢使用不太方便
如果你的key是這樣的['123', '2010/07/21'],其中前一部分為查詢的key,后一部分為時間,用于保證記錄的順序性。這時候你要查詢所有’123′開頭的記錄時,就需要指 定起始條件為 ['123'],并且還必須指定一個終止條件為['123',{}],這樣讓人感覺用起得很不方便。
CommonJS無法用于mapreduce函數(shù)中
在CouchDB 0.11版本中,CommonJS已經(jīng)可以用在view函數(shù)上,但是一直不能用在mapreduce函數(shù)中。這讓我總是重復(fù)一些寫過的代碼。
缺乏document之間完備的包含關(guān)系
在CouchDB 0.11中,map函數(shù)可以通過{_id: doc.other_id}的方式包含另外一個document的引用,在查詢時能夠獲取到對應(yīng)這個文檔的id,但是再進一步,如果我想再獲取被包含的這 個文檔的屬性,那就沒辦法了。希望能夠有辦法通過當(dāng)前集合的查詢,獲取并返回這個包含的文檔的某些屬性。
讀操作總是會落到磁盤上
CouchDB沒有實現(xiàn)自己的緩存。在寫操作中,你可以通過delay commit的方式將寫操作延遲同步,這樣就避免了每次寫操作就需要寫磁盤。但除此之外,CouchDB沒有做任何緩存。對于移動設(shè)備上的CouchDB 來說,寫磁盤可能會好一些,畢竟移動設(shè)備上的flash設(shè)備比服務(wù)器上的傳統(tǒng)磁盤性能要好一些。
沒用的錯誤信息
CouchDB的錯誤信息經(jīng)常讓人摸不著頭腦,根本就看不明白錯誤出在哪里。比如下面這一段,你能告訴我它說明了什么問題嗎。
- {<0.84.0>,supervisor_report,
- [{supervisor,{local,couch_secondary_services}},
- {errorContext,start_error},
- {reason,
- {'EXIT',
- {undef,
- [{couch_auth_cache,start_link,[]},
- {supervisor,do_start_child,2},
- {supervisor,start_children,3},
- {supervisor,init_children,2},
- {gen_server,init_it,6},
- {proc_lib,init_p_do_apply,3}]}}},
- {offender,
- [{pid,undefined},
- {name,auth_cache},
- {mfa,{couch_auth_cache,start_link,[]}},
- {restart_type,permanent},
- {shutdown,brutal_kill},
- {child_type,worker}]}]}}
好了,大概就這些吧。雖然上面說了這么多CouchDB讓人不爽的地方,但是總的來說,我還是很喜歡CouchDB的,雖然有上面一些讓人不爽的地 方,但是它還是能幫我處理很多問題。所以爭論一個東西是否要用,并不是看它能不能滿足所有需求,而是看它能不能滿足你要的核心需求就行了。
英文:http://www.paperplanes.de/2010/7/26/10_annoying_things_about_couchdb.html
原文鏈接:http://blog.nosqlfan.com/html/3667.html
【編輯推薦】