MongoDb C# 驱动程序 - 通过索引字段获取项目非常慢
MongoDb C# Driver - Get item by indexed field very slow
我 运行 在小型本地数据库上获取过滤数据时遇到性能问题。我减少了代码(如下所示)以重现该问题。输出大约2000ms。
一些附加信息:
- 查询的集合包含 135,000 个条目,每个条目有 7 个简单类型
- 当 运行 类似 RoboMongo 的查询时 - db.TickerData.find({_id : ObjectId('5731d39062deb83134772e77')}).explain() - 总执行时间 <1ms
- 我正在使用最新的 MongoDb 服务器和 C# 驱动程序版本
- 数据库是 运行 本地(四核 16Mb Ram)在相同的 dev/debug 环境
- 我注意到在测试除 ID(始终被索引)以外的其他字段时,索引字段和非索引字段之间的性能没有差异
- 我的第一个想法是 .Single() linq 操作在执行单个搜索之前检索所有文档,但从 Google'ing 看来,所有 linq 操作都适合 运行 MongoDB 服务器端查询
代码:
public class UnitTest1
{
public void TestMethod2()
{
Stopwatch sw = new Stopwatch();
sw.Start();
new BaseRepository<TickerData>().GetById("5731d39062deb83134772e77");
sw.Stop();
Debug.Write(sw.Elapsed.TotalMilliseconds);
}
}
public class BaseRepository<T> : MongoBase where T : BaseEntity
{
MongoDatabase DataBase { get; set; }
protected IQueryable<T> Collection { get; set; }
MongoCollection<BsonDocument> mCollection { get; set; }
public BaseRepository()
{
DataBase = Server.GetDatabase("TradingBot");
mCollection = DataBase.GetCollection<BsonDocument>(typeof(T).Name);
Collection = mCollection.AsQueryable<T>();
}
public T GetById(string ID)
{
return Collection.Single(i => i.Id.ToString() == ID);
}
}
更新:
根据@rnofenko 的建议(查看评论)做出了巨大的改进,但似乎仍然很慢?
这是一个棘手的时刻。
您从 System.Linq 调用扩展方法 Single。事实上,您从数据库加载整个集合,并在您的应用程序中通过 ID select。
相反,您需要使用 MongoDB 扩展方法 - 来自 MongoDB.Driver.Linq.[=11= 的 SingleAsync ]
public async Task<T> GetById(string id)
{
return await Collection.SingleAsync(x => x.Id == new ObjectId(id));
}
我 运行 在小型本地数据库上获取过滤数据时遇到性能问题。我减少了代码(如下所示)以重现该问题。输出大约2000ms。
一些附加信息:
- 查询的集合包含 135,000 个条目,每个条目有 7 个简单类型
- 当 运行 类似 RoboMongo 的查询时 - db.TickerData.find({_id : ObjectId('5731d39062deb83134772e77')}).explain() - 总执行时间 <1ms
- 我正在使用最新的 MongoDb 服务器和 C# 驱动程序版本
- 数据库是 运行 本地(四核 16Mb Ram)在相同的 dev/debug 环境
- 我注意到在测试除 ID(始终被索引)以外的其他字段时,索引字段和非索引字段之间的性能没有差异
- 我的第一个想法是 .Single() linq 操作在执行单个搜索之前检索所有文档,但从 Google'ing 看来,所有 linq 操作都适合 运行 MongoDB 服务器端查询
代码:
public class UnitTest1
{
public void TestMethod2()
{
Stopwatch sw = new Stopwatch();
sw.Start();
new BaseRepository<TickerData>().GetById("5731d39062deb83134772e77");
sw.Stop();
Debug.Write(sw.Elapsed.TotalMilliseconds);
}
}
public class BaseRepository<T> : MongoBase where T : BaseEntity
{
MongoDatabase DataBase { get; set; }
protected IQueryable<T> Collection { get; set; }
MongoCollection<BsonDocument> mCollection { get; set; }
public BaseRepository()
{
DataBase = Server.GetDatabase("TradingBot");
mCollection = DataBase.GetCollection<BsonDocument>(typeof(T).Name);
Collection = mCollection.AsQueryable<T>();
}
public T GetById(string ID)
{
return Collection.Single(i => i.Id.ToString() == ID);
}
}
更新: 根据@rnofenko 的建议(查看评论)做出了巨大的改进,但似乎仍然很慢?
这是一个棘手的时刻。 您从 System.Linq 调用扩展方法 Single。事实上,您从数据库加载整个集合,并在您的应用程序中通过 ID select。
相反,您需要使用 MongoDB 扩展方法 - 来自 MongoDB.Driver.Linq.[=11= 的 SingleAsync ]
public async Task<T> GetById(string id)
{
return await Collection.SingleAsync(x => x.Id == new ObjectId(id));
}