2015-04-16 65 views
3

我目前使用的MongoDB遊標的指定者()函數將數據庫結果轉換爲數組:替代的MongoDB cursor.toArray()中的node.js

run = true; 
count = 0; 
var start = process.hrtime(); 
db.collection.find({}, {limit: 2000}).toArray(function(err, docs){ 
    var diff = process.hrtime(start); 
    run = false; 
    socket.emit('result', { 
    result: docs, 
    time: diff[0] * 1000 + diff[1]/1000000, 
    ticks: count 
    }); 
    if(err) console.log(err); 
}); 

此項操作需要我的電腦上約7毫秒。如果我刪除.toArray()函數,那麼該操作大約需要0.15ms。當然,這不起作用,因爲我需要轉發數據,但是我想知道這個功能需要這麼長時間才能做什麼?數據庫中的每個文檔都只包含4個數字。

最後,我希望能夠在一個更小的處理器上運行,比如Raspberry Pi,在這裏它從數據庫中獲取500個文檔並將其轉換爲數組需要大約230ms。這對我來說似乎很重要。或者我只是期待太多?

是否有任何替代方法從數據庫中獲取數據而不使用toArray()?

我注意到的另一件事是整個Node應用程序在獲取數據庫結果時顯着下降。我創建了應該增加每1毫秒計值的簡單間隔功能:

setInterval(function(){ 
    if(run) count++; 
}, 1); 

然後,我會想到的計數值是幾乎相同的時間,但對於16毫秒我的計算機上的時間計數值爲3或4.在Raspberry Pi上,計數值從不增加。什麼是如此之多的CPU使用率?顯示器告訴我,當被要求重複運行數據庫查詢時,我的電腦使用了27%的CPU,Raspberry Pi使用了92%的CPU和11%的RAM。

我知道這是很多問題。任何幫助或解釋都非常感謝。我還是Node和MongoDB的新手。

回答

6

db.collection.find()返回一個遊標,而不是結果,並且打開遊標非常快。

一旦你開始閱讀光標(使用.toArray()或通過遍歷它使用.each().next()),實際的文件正在從數據庫傳輸到客戶端。該操作大部分時間都在進行。

我懷疑使用.each()/.next()(而不是.toArray(),這是在引擎蓋下使用這兩個中的一個)會提高性能,但你可以隨時嘗試(誰知道)。由於.toArray()將讀取內存中的所有內容,因此可能是值得的,儘管聽起來不像你的數據集那麼大。

我真的認爲樹莓派上的MongoDB(尤其是Model 1)並不能很好地工作。如果您不太依賴MongoDB查詢功能,則應考慮使用備用數據存儲。也許即使是內存中的存儲(500個文件乘以4個數字聽起來不像是需要大量的RAM)。

+0

感謝您的快速回答。它讓我明白了很多事情。我嘗試使用.each(),但實際上它有點慢。從數據庫傳輸數據時,是否期望節點應用程序速度變慢? – KMK

+1

@KMK適用於小文檔,即使是大數據集也不會顯着減慢您的應用程序。根據我的經驗,大部分減速將發生在BSON解析中(這是一個同步操作)。隨着平臺的不足,它可能成爲瓶頸。 – robertklep