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分页处理方案(适用于一般数据库的分页方法)》