Mongodb 查询(聚合框架)耗时极慢
Mongodb queries (aggregation framework) take enormously slow time
我的数据集不是很大(>100000 条记录)。
但是我 运行 对它们的汇总查询花费了很长时间。
我在 _type
字段上有一个索引。当我 运行
db.getCollection('product').find({_type:"healthcare"}).count()
我在 0.015 秒内收到响应...
但是当我 运行 例如
db.getCollection('product').aggregate([{$group:{_id:"$_type",sum:{$sum:1}}}])
我正在等待 40 秒才能收到回复。
这样的仅索引聚合查询可能有什么问题?我应该在哪里寻找问题?
MongoDB 版本为 3.0+。 wiredTiger 数据存储。这里是 db.stats()
输出:
{
"collections" : 3,
"objects" : 113090,
"avgObjSize" : 259186.2551949774497189,
"dataSize" : 29311373600.0000000000000000,
"storageSize" : 29317480288.0000000000000000,
"numExtents" : 36,
"indexes" : 4,
"indexSize" : 15379056.0000000000000000,
"fileSize" : 32130465792.0000000000000000,
"nsSizeMB" : 16,
"extentFreeList" : {
"num" : 2,
"totalSize" : 9.85907e+06
},
"dataFileVersion" : {
"major" : 4,
"minor" : 22
},
"ok" : 1.0000000000000000
}
根据 pipeline operators and indexes 上的文档,$group
管道运算符不能使用索引:
The $match
and $sort
pipeline operators can take advantage of an index
when they occur at the beginning of the pipeline.
New in version 2.4: The $geoNear
pipeline operator takes advantage of a geospatial index. When using $geoNear
, the $geoNear
pipeline
operation must appear as the first stage in an aggregation pipeline.
Even when the pipeline uses an index, aggregation still requires
access to the actual documents; i.e. indexes cannot fully cover an
aggregation pipeline.
Changed in version 2.6: In previous versions, for very select use cases, an index could cover a pipeline.
因此您的 $group
聚合很慢,因为它将使用完整的集合扫描。
但是,值得注意的是,您要比较的 find
查询的 aggregate
等效项是:
db.getCollection('product').aggregate([
{$match: {_type: 'healthcare'}},
{$group: {_id: null, sum: {$sum: 1}}}
])
并且由于该查询以 $match
运算符开头,因此它将使用索引并且性能应该更具可比性。
我的数据集不是很大(>100000 条记录)。 但是我 运行 对它们的汇总查询花费了很长时间。
我在 _type
字段上有一个索引。当我 运行
db.getCollection('product').find({_type:"healthcare"}).count()
我在 0.015 秒内收到响应...
但是当我 运行 例如
db.getCollection('product').aggregate([{$group:{_id:"$_type",sum:{$sum:1}}}])
我正在等待 40 秒才能收到回复。
这样的仅索引聚合查询可能有什么问题?我应该在哪里寻找问题?
MongoDB 版本为 3.0+。 wiredTiger 数据存储。这里是 db.stats()
输出:
{
"collections" : 3,
"objects" : 113090,
"avgObjSize" : 259186.2551949774497189,
"dataSize" : 29311373600.0000000000000000,
"storageSize" : 29317480288.0000000000000000,
"numExtents" : 36,
"indexes" : 4,
"indexSize" : 15379056.0000000000000000,
"fileSize" : 32130465792.0000000000000000,
"nsSizeMB" : 16,
"extentFreeList" : {
"num" : 2,
"totalSize" : 9.85907e+06
},
"dataFileVersion" : {
"major" : 4,
"minor" : 22
},
"ok" : 1.0000000000000000
}
根据 pipeline operators and indexes 上的文档,$group
管道运算符不能使用索引:
The
$match
and$sort
pipeline operators can take advantage of an index when they occur at the beginning of the pipeline.New in version 2.4: The
$geoNear
pipeline operator takes advantage of a geospatial index. When using$geoNear
, the$geoNear
pipeline operation must appear as the first stage in an aggregation pipeline.Even when the pipeline uses an index, aggregation still requires access to the actual documents; i.e. indexes cannot fully cover an aggregation pipeline.
Changed in version 2.6: In previous versions, for very select use cases, an index could cover a pipeline.
因此您的 $group
聚合很慢,因为它将使用完整的集合扫描。
但是,值得注意的是,您要比较的 find
查询的 aggregate
等效项是:
db.getCollection('product').aggregate([
{$match: {_type: 'healthcare'}},
{$group: {_id: null, sum: {$sum: 1}}}
])
并且由于该查询以 $match
运算符开头,因此它将使用索引并且性能应该更具可比性。