count 在MongoDB 存在着不小的問題,對比關係型數據庫,無固定結構的數據存儲對 count 函數存在着天然的缺陷,在大量數據情況下,count 函數計算非常慢,這對分頁查詢產生了不小的影響。
毫無疑問,count 的查詢語句使用了索引比沒有使用索引快上1000倍不止,因此,一定要用 explain 函數看看,count 的查詢語句是否使用了索引。
但是這也不能從根本上解決問題,count 的計算速度隨數據量的增加而變慢,當查詢的量超過10w,100w時,count 幾乎是沒有用的。既然這是由MongoDB存儲的方式導致的,所以我並不打算去攻克這個難題。下面提供的兩個我的解決方案。
1、Top N 的查詢方式
Top N 的意思是,我的分頁查詢只需要返回查詢的集合中的Top N 條。例如,查詢語句篩選出了10w條數據,但是我只取Top 1w。這樣就避免了使用 count 函數去計算 10w 條數據,因而速度將會提高10倍。使用語句如下:
(1)普通查詢
db.getCollection('testCollection').find({}).limit(10000).count(true)
(2)Aggregate
db.getCollection('testCollection').aggregate([{
"$match": {
}
}, {
"$limit": 10000
}, {
"$count": "countName"
}])
需要置 count() 爲 true(默認爲 false),當 count 置爲 true 時, limit 生效,如果查詢的集合超過 10000 條,那麼 count 取 10000 條。因此查詢的速度並不會再受數據量不斷增加帶來的影響。
Top N 可以結合篩選一起使用,可避免 Top N 查詢不完全的問題。
2、採用谷歌搜索和百度分頁方式
谷歌和百度的分頁方式完全避免了使用 count 函數,詳情參考 《MongoDB分頁處理方案(適用於一般數據庫的分頁方法)》