2014-10-09 162 views
0

這種查詢可以去任何更快:蒙戈聚集慢

db.foo.aggregate([ 
    {"$match": {"uid": {"$in": ["40001"]}}}, 
    { 
     "$group": { 
      "read": {"$sum": {"$cond": ["$read", 0, 1]}}, 
      "imp": {"$sum": {"$cond": ["$important", 1, 0]}}, 
      "_id": {"group_by": "$group_by", "ip_group": "$ip_group"}, 
      "date": {"$min": "$date_meta.dt"}, "count": {"$sum": 1} 
     } 
    },  
    {"$sort": {"start_time": -1}} 
]) 

在1mil的〜。如果uid =「40001」(大約900000 - 90%的集合)對於其他所有uid聚合來說要快得多,則大約需要2,3秒。所以看起來mongo花費大部分時間來減少結果。 我厭倦了刪除條件陳述,但沒有獲得任何速度。所以看起來好像什麼都不能做,但我可能在某個地方忽略了這一點。 哦,我嘗試了索引,並刪除$排序選項,但沒有改進。

+1

$ sort沒有效果,因爲$ group stage沒有字段** start_time **,否則會變慢。我認爲這取決於** $ group **舞臺上的團體數量;如果** $ group **的** _ id **是一個常數(最後只有一組),我想這對您來說是極端的速度。順便說一下,700MB還需要從磁盤讀取一些時間。 – Wizard 2014-10-09 14:31:48

+0

不mongo通過mmap()保存內存中的所有記錄嗎?我不認爲每次閱讀後都會刷新所有數據,否? – dakt 2014-10-09 15:49:42

+0

你說得對。它在第一次讀取後被緩衝。 – Wizard 2014-10-10 00:51:06

回答

1

如果MongoDB需要將大量文檔加載到內存中(900,000是一個很好的數量),這將需要一些時間。改善這個問題的方法是...

  • 改善硬件
  • 使用分片來分配負載

拆分將工作做好,如果組顯著減少文件的數量。這是因爲最初的小組工作將在每個碎片上完成,然後在MongoS上重新完成。

+0

改進硬件意味着什麼?收集的大小是由db.collection.stats()報告的705695808字節。所以有足夠的內存和機器運行4個CPU。現在我可以做平行的工作?如果這甚至是可能的?也許通過使用$ out並彙總最終的集合?分片也不是ATM的選項。 – dakt 2014-10-09 14:08:10

+0

我的意思是,這是導致搜索速度緩慢的一件事。如果你有一個關於'uid'的索引,除了我的建議之外,沒有其他任何事情可以做,而不需要重新組織數據。 '$ out'會讓檢索結果變慢。 – 2014-10-09 15:47:50