2012-09-11 190 views
0

我是mongo的新用戶(具有豐富的mysql經驗),它似乎有一些有趣的優點和缺點。顯然,專業人士可以容納的數據大小以及可以寫入記錄的速度。我有一個應用程序,我正在向一個集合寫很多日誌,到目前爲止我已經有大約7米了。我的問題是,一個看似簡單的查詢需要很長時間才能真正實現。讓我解釋。mongo聚合速度

我收藏有7米文件:

> db.alpha2.count() 
7257619 

現在我想指望所有記錄對於給定的CID,並且具有比一些數量較少的時間戳(本例中在未來有時間戳,所以應該什麼都算):

> db.alpha2.find({'ts': {'$lt': 1446457607}, 'cid': '2636518'}).count() 
7257619 

這是問題的查詢,它需要一個完整的58秒這個號碼還給我!從概念上講,這是一個非常簡單的查詢,並會在一定程度上相當於在SQL中的世界:

select count(*) from alpha2 where cid=2636518 and ts<1446457607 

我沒有等價表,但我認爲這將需要小於0.1秒基於在mysql中運行根據我的經驗。那麼我該怎麼做?我計劃對大於7m記錄的數據集進行大量聚合計數。我也做了一些稍微困難的事情(地圖縮小),而且更糟(幾分鐘)。我需要這個不到一秒鐘。我究竟做錯了什麼?這是mongo預計的時間成本嗎?

我把一個指標的TS值與在此之前我的時間在上面查詢:

db.alpha2.ensureIndex({ts:1}) 
+0

只有ts列上的索引,如果ts <1446457607匹配的記錄數很大,SQL也可能需要很長時間。您需要在cid和ts上使用複合索引來加快速度。 – gkamal

回答

4

爲了確定count(),MongoDB的必須找到所有匹配的文件。

可以explain()查詢,看看如何使用索引:

db.alpha2.find({'ts': {'$lt': 1446457607}, 'cid': '2636518'}).explain() 

特別是要儘量減少nscannedObjects(掃描的文件數)。

你最好的情況下的標準方案是在涉及計數的所有字段上進行索引(並確保索引符合可用RAM)。

所以,你的指標應包括cid還有:

db.alpha2.ensureIndex({ts:1, cid:1}) 

如果你正在做頻繁的計數,你可能會更好地存儲,並通過像incremental map/reduce進程更新這些是否適合您的使用案例。

+0

MongoDB的問題跟蹤器中也有一些開放的建議,用於提高各種用例(集合中的所有文檔,每個屬性,查找不同值,...)的計數性能。例如:[SERVER-1752](https://jira.mongodb.org/browse/SERVER-1752)(提高count({attr:val})的性能)。 – Stennie

+0

請注意,SERVER-1752已在2.3.2開發版中得到解決,因此在MongoDB 2.4生產版本​​中,對於一些常見使用情況,計數性能將顯着提高。 – Stennie