为什么聚合框架的$ max-function比迭代游标慢?

时间:2013-03-14 09:49:32

标签: java mongodb

我得到了大约300,000个条目的数据集。为了存储该数据,我正在使用当前版本的mongodb 2.2.3。我的问题是如何通过使用聚合框架来提高搜索性能?

这是我存储数据的一个示例:

{
    "_id":"654311649875645643131564",
    "@type":"K",
    "dataSourceA":{
        "name": "abc",
        "price": 12.99
    },
    "dataSourceB":{
        "name": "xyz"
    }
}

在我切换到较新版本的mongodb之前,我处理了例如没有聚合框架的最大值如下:

searchQuery = new BasicDBObject("dataSourceA.price", -1);
DBCursor cursor = collection.find().sort(searchQuery).limit(1);

此操作大约需要0.921 secs

现在我尝试使用聚合框架来实现相同的结果,但希望更快地找到最高价格。这是我的方法:

DBObject match = new BasicDBObject("$match", new BasicDBObject("@type", "K"));
DBObject fields = new BasicDBObject("dataSourceA.price", 1);          
DBObject project = new BasicDBObject("$project", fields);
DBObject groupFields = new BasicDBObject("_id", 1);
groupFields.put("max", new BasicDBObject("$max", "$dataSourceA.price"));

DBObject group = new BasicDBObject("$group", groupFields);

Iterable<DBObject> results = 
    collection.aggregate(match, project, group).results();

但是此操作需要大约4.837 secs才能找到最高价格。那么我的查询可以改进什么呢?我认为像这样的数据库应该比在java中迭代游标更快,在我错的时候纠正我。

1 个答案:

答案 0 :(得分:1)

这有很多原因。

首先,对于光标示例,您只是运行一个查询,对子文档字段上的所有根文档进行排序,很可能是索引的。无论你怎么看,它都会更快。

第二个$max实际上是一个$group运算符,这意味着它是适合您的查询集的所有文档的内存操作(全部300,000个),因此MongoDB正在计算对于结果集中的所有文档,每个文档的多值字段的最大值(在_id上分组)。

由于$max的工作方式,您立即失去了从索引光标中获得的即时排序功能。

不仅如此,您还在聚合中途进行预测,使MongoDB进一步有力地分割您的文档。

所以不,它不应该比迭代已排序的索引游标更快。