CouchDB用起來可能不是很舒服

最近我花了一個星期研究NoSQL,我有一個400萬記錄的MySQL速度比較慢,準備遷移到NoSQL上,由於主要是一些JSON格式的文檔,原本序列化存在MySQL中的,由於看上了Erlang這個號稱很是牛X的平臺,挑中了CouchDB,但導入40萬有效測試數據,在本地運行的時候,發現速度特別慢(本地機器爲2011年的iMac,配備16G內存,根本不弱的),並且查詢功能很弱,可能還沒到成熟的時候。javascript

CouchDB特色:java

面向文檔數據庫,不須要範式,直接存儲JSON就能夠,CouchDB默認會生成 _id,_rev 兩個鍵,_id是一條記錄(文檔)的惟一標識,若是不提供_id,_id會自動生成,也能夠手動指定_id,好比用手機號作主鍵:node

{'_id' : '+86186*****', name: '' }

 _rev是其版本號,每更新一次 _rev就會自動發生變化,格式爲
shell

5-6a8617596d2adfea245662df0df611ao

,標識第5個版本,後面是HASH簽名,能夠經過_rev尋找到全部的歷史版本,因此用來作須要存儲版本的文檔系統應該很是不錯,好比多人協做修改一篇文檔等應用。
數據庫

CouchDB提供RESTful接口訪問,只須要執行http請求就能完成增刪改功能,好處是,只須要命令行cURL就能夠開始工做了,不須要特別的驅動,好比:獲取一篇文檔:json

curl -X GET http://127.0.0.1:5984/dbname/_id

就能夠了,而壞處是,http協議的效率並不高,尤爲是若是執行一個頁面須要多個請求的時候,用MySQL能夠公用一個打開的連接就能夠不斷執行查詢,而用http?得想一想怎麼樣讓http複用一個socket連接,因此越是入門簡單,後面的麻煩就越多!
數組

CouchDB的查詢功能很是弱,CouchDB如何執行查詢呢?不一樣於MySQL,扔一條SQL過去就得了。得爲每一次查詢建立一個view,view的格式:app

{"map": "function(doc){ emit( key,  value); } "}

,這裏面的function必須是一個字符串,而不能是javascript的合法語句,因此你寫一個稍微複雜一點的語句,得先保證在node/console裏調試好,而後把他轉換成字符串,而後再構造出合法的json字符串post過去,這個過程很是的痛苦。並且這個view在第一次查詢的時候速度會慢的嚇死人,40萬條數據,執行一次須要的時間大概要5分鐘左右,400萬條,我就不敢測試了,但stackoverflow上有網友說他跑了4個小時還沒跑出結果來,由於這個map可不存在什麼優化的地方,map就是一條條在運行,因此無論作什麼查詢,都要遍歷全部doc,能不慢麼!
curl

另外,view其實也是像其餘普通的記錄同樣實實在在存在數據庫裏的,能夠經過 _utils 看到,view中是不能夠傳遞變量的(臨時view能夠),好比在一個庫裏存在 member 數據有 name, email, city等,須要查詢 city爲"shenzhen"的member,那麼怎麼辦?第一用臨時view: temp_view,構造動態的查詢map語句:socket

curl http://127.0.0.1:5984/dbname/_temp_view?include_docs=true -H 'Content-Type: application/json'  -d \
'{"map": "function(doc){  if(doc.city.match(/shenzhen/) ) emit(doc._id, 1 );  }" }'

最好把這個 _temp_view 存儲成永久的view,不然每次查詢一個新的city都會很慢的,一旦執行過一次查詢,後面的訪問就會比較快,可是前提是:得執行過一次查詢!

但若是存儲爲永久view,就須要寫死 shenzhen這個字符串在view中,這種傳遞變量的辦法顯然是不可取的,很是呆板,難道我要查詢一個 city爲 shenzhen的就得新建一個 view,那麼全國那麼多city,是否是每個都要新建一個city?view這種方式查詢真的很愚蠢!

除了temp_view外,到底有沒有辦法能夠動態傳遞參數的?能夠啊 startkey 和 endkey啊,但這兩個參數光從名字就能夠看出設計的是多麼愚蠢了。

好這樣查詢,先建立一個view,保存爲 member/city_query

'{"map": "function(doc){  emit([doc.city, doc._id],   1 );  }" }'

接下來就能夠痛快查詢啦:

curl \
http://127.0.0.1:5984/dbname/_design/member/_view/city_query?startkey=[shenzhen]&endkey=[shenzhen]
-H 'Content-Type: application/json'

這個語句是不能運行的,須要手動將中括號 [] 轉義。看就是這麼無聊。

執行的過程是這樣的:startkey傳遞了一個數組參數,只有一個值 shenzhen,在view的map裏,emit再也不是一個普通的key,而是一個數組,startkey第一個值對應於emit的第一個參數中的第一位即 doc.city, 結果就會檢索 city的值>=shenzhen,再指定一個endkey就OK了啊!能夠想一想,這個map仍是會遍歷全部的記錄!


這樣的設計的很低級,並且很是很差用,若是我要查詢 正則匹配怎麼辦?老老實實建立一個新的view? 結果就是若是你的查詢比較多樣化,裏面的view可能比數據還多!

最終個人結論是,不要在大數據上嘗試CouchDB,不要在須要頻繁查詢的地方使用CouchDB,不要在須要大量彙總、分析數據的地方使用CouchDB,他只適合最多幾千條數據的小博客、小文檔系統,而且不須要各類花式查詢的地方,他的性能不如想一想中來的那麼暢快,並且CouchDB內部存儲就是實實在在的文件而已,沒有什麼優化,提高查詢速度也不是CouchDB最近的目標,他們更多關注在功能上而非性能。而且CouchDB的開發初衷是Apache基金會的一廂情願,並不是工程需求,因此若是選擇NoSQL,要儘量找在工程需求中開發出來的數據庫。

相關文章
相關標籤/搜索