Why is my .NET MongoDb Driver Query Horribly Slow?

时间:2016-02-12 21:45:01

标签: mongodb mongodb-query mongodb-.net-driver

I run a query to $.ajax({ url: 'json/local_json_file.json', dataType: 'json', //or application/json type: 'get', cache:'false', success: function(data) { $(data).each(function(index,value) { //some code }); } }); directly in Mongo (Robomongo, CLI, whatever) and it takes less than a second on several hundred thousand items:

select all items where field1=x, field2 =y, and field3=z

I then try to run the exact same thing from C# driver and it lags out(only "Aggregate filter" code is relevant, everything else is for context):

db.items.find( { 
    $and: [ 
        { CreatingOrgId: 1 }, 
        { LocationId: 941 },
        { StatusId: 1}
    ] 
} )

What's my mistake here? Here are the queries as mongo sees them:

enter image description here

Edit: Looks like mapping the items to item object is what's killing my query to some degree. It's fairly fast (couple of seconds for a huge number of records) without the mapping, like so:

FilterDefinition<BsonDocument> locationsFilter;  = Builders<BsonDocument>.Filter.Eq("LocationId", 941);
FilterDefinition<BsonDocument> orgFilter = Builders<BsonDocument>.Filter.Eq("CreatingOrgId", 1);
FilterDefinition<BsonDocument> statusFilter = Builders<BsonDocument>.Filter.Eq("StatusId", 1);

FilterDefinition<BsonDocument> aggregateFilter = locationsFilter & statusFilter & orgFilter;

        List<ItemViewModel> stuffList = mongoItemsCollection
                                             .Find(aggregateFilter)
                                             .Project(x => Mapper.Map<BsonDocument, StuffViewModel>(x))
                                             .ToListAsync().Result;

Edit 2: Looks like automapper is a HUGE part of the problem here (taking the bson "item" object and converting it to a .NET view model). I am still interested in optimization of the .NET --> mongo query itself though (ignoring the automapper part), if anyone wants to answer.

2 个答案:

答案 0 :(得分:3)

在C#中运行.ToListAsync()时,将访问并返回查询的整个结果。

当您在命令行上运行.find()时,只返回20(默认情况下)。

命令行上的一个更等效的测试是.find().toArray(),它也将访问并返回所有结果。或者您可以在C#查询中设置限制。

如果您的完整结果集远大于shell批量大小,则可能会导致结果中的一些差异。如果未覆盖查询(即查询中的所有字段和返回的所有字段不在同一索引中),并且访问的数据不在内存中但是从磁盘访问,则差异会更大。

答案 1 :(得分:1)

假设您在3个字段上有索引,那么问题是mongo和C#查询之间的字段顺序不同。

C#查询是:LocationId,StatusId,CreatingOrgId

Mongo查询是:CreatingOrgId,LocationId,StatusId

您可以通过首先启用性能分析来验证MongoDB中的确切查询:

db.setProfilingLevel(2); // Profiles all queries.

然后,使用以下方法查找确切的查询:

db.system.profile.findOne();