2010-04-08 43 views
27

在聽到MongoDB性能的諸多好消息之後,我們決定讓Mongodb嘗試解決我們遇到的問題。我開始將我們在多個mysql數據庫中的所有記錄移動到mongodb中的單個集合中。這導致收集了29百萬個文件(其中每個文件至少有20個字段),這需要大約100 GB的空間。我們決定將它們全部放在一個集合中,因爲所有文檔具有相同的結構,並且我們要查詢並彙總所有這些文檔的結果。MongoDB在聚合查詢方面的表現

我創建了一些索引來匹配我的查詢,否則即使簡單count()也需要很長時間。但是,諸如distinct()和group()之類的查詢仍然需要很長時間。

實施例:

// creation of a compound index  
db.collection.ensureIndex({'metadata.system':1, 'metadata.company':1}) 

// query to get all the combinations companies and systems 
db.collection.group({key: { 'metadata.system':true, 'metadata.company':true }, reduce: function(obj,prev) {}, initial: {} }); 

我把一看的mongod日誌和它有很多這樣的線(在執行上述查詢):

Thu Apr 8 14:40:05 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1048890 nreturned:417 154ms 
Thu Apr 8 14:40:08 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1050205 nreturned:414 430ms 
Thu Apr 8 14:40:18 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1049748 nreturned:201 130ms 
Thu Apr 8 14:40:27 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1051925 nreturned:221 118ms 
Thu Apr 8 14:40:30 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1053096 nreturned:250 164ms 
... 
Thu Apr 8 15:04:18 query database.$cmd ntoreturn:1 command reslen:4130 1475894ms 

此查詢了1475894ms其比我想象的要長(結果列表大約有60個條目)。首先,鑑於我收藏的大量文件,這是否是預期的?一般來說聚合查詢在MongoDB中會如此緩慢?關於如何改善表現的任何想法?

我正在一臺雙核和10GB內存的單機上運行mongod。

謝謝。

+1

那麼這個問題太老了,當你搜索MongoDB聚合框架時,仍然會涉及搜索引擎。馬里奧你沒有提到你的MongoDB版本,因爲他們在2.4中改進了很多AF,而且我在一個蹩腳的m1上做了這個。 EC2與3.7G內存在一個69米的集合,它的速度比以前更快。你有沒有嘗試過新版本,或者你有不同的方法?當然,AF和MapReduce有很多基準,但看看10Gen的最新版本http://blog.mongodb.org/post/62900213496/qaing-new-code-with-mms-map-reduce-vs -aggregation tnx – Maziyar 2013-11-03 02:16:08

+0

感謝您的評論。這是在2010年,我相信我們正在使用MongoDB 1.4.0之類的東西。已經有一段時間了,我相信很多事情在MongoDB中都有變化,但自那年晚些時候以來我一直沒有在這個項目中工作:) – 2013-11-05 17:34:54

+0

感謝Mario的回覆。我剛開始使用MongoDB(大約一年),只是想知道你的項目發生了什麼。無論如何祝你好運:) – Maziyar 2013-11-06 03:19:07

回答

22

這個想法是,您可以通過在分佈在多臺機器上的分片數據庫上使用MapReduce來提高聚合查詢的性能。

我在同一臺機器上對Mongo的Mapreduce與Oracle中的group-by-select語句進行了一些比較。我確實發現Mongo大約慢了25倍。這意味着我必須在至少25臺機器上分割數據,才能獲得與Oracle在單臺機器上交付的Mongo相同的性能。我使用了大約1400萬個文檔/行的集合/表格。

通過mongoexport.exe導出mongo中的數據,並將導出的數據作爲Oracle中的外部表使用,並且在Oracle中執行group-by比使用Mongo自己的MapReduce快得多。

+0

這將是非常有用的知道哪個版本的MongoDB。 – nilskp 2013-08-14 13:18:50

+0

我相信這是類似於1.4.0版本的東西。這是在2010年。 – 2013-11-06 17:19:34

4

聚合(map reduce或其他)在mongo中非常緩慢,因爲它是由JavaScript VM而不是數據庫引擎完成的。這仍然是時間序列數據的這個(非常好,imo)db的限制。

+1

從v2.2開始,聚合管道使用[本地操作](http://docs.mongodb.org/manual/core/aggregation-introduction/#aggregation-pipelines)。 – Tamlyn 2015-09-03 13:17:20

8

夫婦的事情。

1)您的小組查詢正在處理批次的數據。雖然您的結果集很小,但它看起來像是在對您的集合中的所有數據進行表格比例縮放以產生小的結果。這可能是緩慢的根源。爲了加快速度,您可能希望在查詢運行時通過iostat查看服務器的磁盤性能,因爲這可能是瓶頸。

2)正如在其他答案中已經指出的那樣,group命令使用JavaScript解釋器,這會限制性能。您可以嘗試使用在2.1版中作爲測試版發佈的新聚合框架(注意:截至2012年2月24日這是一個不穩定的版本)。請參閱http://blog.mongodb.org/post/16015854270/operations-in-the-new-aggregation-framework以獲得很好的介紹。這不會克服(1)中的數據量問題,但它是用C++實現的,如果JavaScript時間是瓶頸,那麼它應該快得多。

3)另一種方法是使用增量式map-reduce以分組結果生成第二個集合。想法是,您將運行map-reduce作業來聚合一次結果,然後定期運行另一個map-reduce作業,將新數據重新還原到現有集合中。然後,您可以從您的應用程序查詢第二個集合,而不是每次都運行組命令。