使用C#驱动程序的MongoDB性能较慢,而不是在命令行中

时间:2014-10-03 13:42:53

标签: c# performance mongodb

我正在探索MongoDB以检查我们是否可以将它用作我们产品的noSQL存储。 一切看起来都很好,但在我们的C#应用​​程序中却相当慢。查询大约需要120到140毫秒才能返回结果,这对我们的应用程序来说是不可接受的(比MS SQL慢10倍)。 起初我以为它可能与$in运算符和我过滤的Guid字段有关,但事实并非如此。

目前我已经创建了一个小测试来衡量特定查询的性能。该方法如下所示:

public IQueryable<T> QueryTest<T>(string collection, IEnumerable<Guid> shouldBeIn, string fieldName)
{
    var dataModelCollection = MongoDatabase.GetCollection<T>(collection);
    var findResult = dataModelCollection
                            .FindAll()
                            .ToList();  //Doing this on purpose, so the query is executed immediatly. Just for this test!
                                        //This action takes about 110~140ms.
    return findResult.AsQueryable();
}

显然这是测试代码,因为我不会在实际代码中使用ToList()并稍后返回IQueryable

当我在MongoDB控制台中运行此查询时,它返回0ms的结果(根据解释)

> db.StoreData.find().explain()
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 21,
        "nscannedObjects" : 21,
        "nscanned" : 21,
        "nscannedObjectsAllPlans" : 21,
        "nscannedAllPlans" : 21,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "server" : "mymongodbserver:27017",
        "filterSet" : false
}

_id字段指定了一个索引,StoreId字段也指定了一个索引,因为我想稍后在StoreId上过滤。

两个查询(C#和控制台)都在同一台机器上执行。我也多次运行测试并且也运行了.reIndex()命令几次。

有关如何进行的任何想法?

修改

它是一个非常小的数据库,只有一点点测试数据/记录。根据要求,返回了 21条记录,我认为explain()方法的结果也说明了这一点。 我也跑了toArray()。我不知道这会有什么帮助,但这是结果的一部分,因为在这里复制21个对象可能并不是很有用。

{
        "_id" : ObjectId("542e847e048b8b0f704a7834"),
        "StoreId" : BinData(3,"/FQLn0k/hkSofM9WvEsNKQ=="),
        "Shelves" : [
                {
                        "ShelveId" : BinData(3,"iCDhfhi6z0adh2haWjrzoQ=="),
                        "Name" : "Shelve 1",
                        "Type" : 0
                }
        ],
        "Doors" : [ ]
},
{
        "_id" : ObjectId("542e847e048b8b0f704a7835"),
        "StoreId" : BinData(3,"p7TkqeFrGEOAWtv0RZ4YjQ=="),
        "Shelves" : [ ],
        "Doors" : [ ]
},

EDIT2

我在我的StoreData集合中添加了更多数据,以查看返回很多(100.000)文档是更快还是更慢。 在MongoDB客户端(mongodb.exe)中,我获得了巨大的快速结果。

> db.StoreData.find().explain()
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 100021,
        "nscannedObjects" : 100021,
        "nscanned" : 100021,
        "nscannedObjectsAllPlans" : 100021,
        "nscannedAllPlans" : 100021,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 781,
        "nChunkSkips" : 0,
        "millis" : 53,
        "server" : "cp-crossbario:27017",
        "filterSet" : false
}

如您所见,返回约100.000个结果的时间是 53毫秒

通过MongoDB驱动程序运行FindAll().ToList()方法会导致接收 5075毫秒中的所有文档。相当不同!

我运行它的机器上的更多背景信息: 我在西欧地区设置了2台Azure Standard_A2计算机(2核,3.5GB内存)。

其中一台机器正在运行MongoDB数据库。我已在C:\MongoDBC:\MongoDB\bin\data上的数据目录中安装了此文件。这仅用于测试目的。当然,没有真正的生产系统可以在这个驱动器上安装日期。

测试数据库的大小约为135MB。

在另一台机器上,我安装了测试客户端,控制台应用程序使用MongoDB C#驱动程序和MongoDB.exe。两者都通过相同的HTTP端点连接到数据库。

EDIT3

我刚刚在没有QueryTest的情况下运行了<T>方法,所以现在我回复了原始的&#39; BsonDocument秒。奇怪的是,它甚至更慢。 100.000文件现在需要大约8000毫秒返回,而返回POCO则返回~5000毫秒。

2 个答案:

答案 0 :(得分:4)

你在shell中进行比较的问题是shell在运行.explain()时,实际上并没有回退任何数据。实际上,您已经消除了整个网络堆栈。因此,您看到的53毫秒是服务器迭代所有数据所需的时间。由于您在Azure中运行,我非常确定网络将占用大部分开销。您可以通过同时运行网络捕获来证明这一点,并查看TCP请求需要多长时间。

此外,当查询这么多结果时,MongoDB会批量发送结果。这意味着它不仅仅是一次网络往返。相反,它是其中的一些,每个都增加了时间的开销。

答案 1 :(得分:1)

我在1411毫秒检索了100,000条记录,问题应该是其他问题,例如硬故障或...... 如果你想在foreach循环中使用它,你可以避免&#39; .ToList()&#39;代码使用结果作为MongoCursor