我正在探索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:\MongoDB
和C:\MongoDB\bin\data
上的数据目录中安装了此文件。这仅用于测试目的。当然,没有真正的生产系统可以在这个驱动器上安装日期。
测试数据库的大小约为135MB。
在另一台机器上,我安装了测试客户端,控制台应用程序使用MongoDB C#驱动程序和MongoDB.exe。两者都通过相同的HTTP端点连接到数据库。
EDIT3
我刚刚在没有QueryTest
的情况下运行了<T>
方法,所以现在我回复了原始的&#39; BsonDocument
秒。奇怪的是,它甚至更慢。 100.000文件现在需要大约8000毫秒返回,而返回POCO则返回~5000毫秒。
答案 0 :(得分:4)
你在shell中进行比较的问题是shell在运行.explain()时,实际上并没有回退任何数据。实际上,您已经消除了整个网络堆栈。因此,您看到的53毫秒是服务器迭代所有数据所需的时间。由于您在Azure中运行,我非常确定网络将占用大部分开销。您可以通过同时运行网络捕获来证明这一点,并查看TCP请求需要多长时间。
此外,当查询这么多结果时,MongoDB会批量发送结果。这意味着它不仅仅是一次网络往返。相反,它是其中的一些,每个都增加了时间的开销。
答案 1 :(得分:1)
我在1411毫秒检索了100,000条记录,问题应该是其他问题,例如硬故障或...... 如果你想在foreach循环中使用它,你可以避免&#39; .ToList()&#39;代码使用结果作为MongoCursor