1、文檔結構範例
{ _id: xxxx, user: 'xiaoming', level: 5, from: 'iPhone', info: 'something wrong' }
2、場景:user為'xiaoming'的文檔有六、七百萬條
3、問題:怎麼提升aggregate+group+sum速度
aggregate([ {$match:{user: 'xiaoming', info:{$regex:'wrong'}}}, {$group:{_id:null, count:{$sum:1}}} ])
用上面這個來統計xiaoming帶有wrong的文檔數量,結果
{"_id": null, "count": 2299999 }
耗時30s-40s。 user、info、user+info三種索引都嘗試過,速度都沒有提升
baidu、google查到‘帶條件計數慢無解’
怎麼提升效率,10s以內能實現嗎
首先要說明的一個問題是,對於OLAP型的操作,期望不應該太高。畢竟是對於大量資料的操作,光從IO就已經遠超通常的OLTP操作,所以要求達到OLTP操作的速度和並發是不切實際的,也是沒有意義的。但並不是說一點優化空間也沒有。
的索引都沒有意義。在找到600w條資料之後還有一個對600w資料的我們先從索引入手。在沒有索引的前提下,找出600萬條
{user: "xiaoming"}
需要多少時間?全表掃描COLLSCAN
從700w條資料找出600w條,跟隨1億條資料找出600w條顯然是兩個概念。命中索引IXSCAN
,這個差異就會小很多,幾乎可以忽略。所以你說{user: 1}
這個索引沒有作用是不對的,可能只是因為集合資料量太少看不出差異而已。順便應該提一下看效率是否有差異應該看執行計劃,不要看執行時間,時間是不準確的。{user: "xiaoming"}
需要多少时间?全表扫描COLLSCAN
从700w条数据中找出600w条,跟从1亿条数据中找出600w条显然是两个概念。命中索引IXSCAN
,这个差异就会小很多,几乎可以忽略。所以你说{user: 1}
这个索引没有作用是不对的,可能只是因为集合数据量太少看不出差异而已。顺便应该提一下看效率是否有差异应该看执行计划,不要看执行时间,时间是不准确的。在有
user
索引的前提下,结果仍然有600w条,剩下的部分是个regex
,regex
无法命中索引,所以不管有没有对info
的索引都没有意义。在找到600w条数据之后还有一个对600w数据的filter
操作。唯一对这个操作可能有帮助的只有全文索引
在有user
索引的前提下,結果仍然有600w條,剩下的部分是個regex
,regex
無法命中索引,所以不管有沒有對filter
操作。唯一對這個操作可能有幫助的只有全文索引
,但全文索引並不能完全取代正規則,具體問題需要讀一下文件。考慮全文索引可行的情況下,可以建立複合索引: 對應地查詢應該改為: 關於複合全文索引的介紹參考這裡,仍然是有些限制需要注意。這樣優化之後預計在同樣的硬體下能降到20s以內,跟你要的10s內還有一段距離。原因開頭說了,對OLAP就不能期待這麼高。如果你真有這方面的需求,就應該從源頭開始,考慮:
或info
每次欄位有更新或插入時就做好計數
不了解,不過能不能分成兩個match會不會好一點呢。 。
類似
主要我認為正規花時間。
有index的話,index一下user。
實時性要求不高 可以定時統計 + 快取