简体   繁体   English

MongoDb C#驱动程序-通过索引字段获取项目非常慢

[英]MongoDb C# Driver - Get item by indexed field very slow

I ran into performance issues when fetching filtered data on a small local database. 在小型本地数据库上获取过滤数据时,我遇到了性能问题。 I reduced the code (as below) to reproduce the issue. 我减少了代码(如下所示)以重现该问题。 The output is about 2000ms. 输出约为2000ms。

Some additional information: 一些其他信息:

  • The queried collection contains 135,000 entries with 7 simple types each 查询的集合包含135,000个条目,每个条目有7种简单类型
  • When running a similar query in something like RoboMongo - db.TickerData.find({_id : ObjectId('5731d39062deb83134772e77')}).explain() - the totalExecutionTime is <1ms 在类似RoboMongo的查询中运行类似查询时-db.TickerData.find({_ id:ObjectId('5731d39062deb83134772e77')})。explain()-totalExecutionTime为<1ms
  • I am using the latest MongoDb server and C# driver versions 我正在使用最新的MongoDb服务器和C#驱动程序版本
  • The database is running locally (quad core 16Mb Ram) on the same dev/debug environment 数据库在同一开发/调试环境中本地运行(四核16Mb Ram)
  • I noticed no difference in performance between indexed and non indexed fields when testing on other fields than the ID (which is always indexed) 在除ID(始终为索引)之外的其他字段上进行测试时,我发现索引字段和未索引字段之间的性能没有差异
  • My first though was that the .Single() linq operation retrieves all the documents before doing a single search but from Google'ing it seems that all linq operations is transposed to MongoDB server side queries 不过,我的第一个操作是.Single()linq操作在执行单个搜索之前会检索所有文档,但是从Google看来,所有linq操作似乎都已转换为MongoDB服务器端查询

Code: 码:

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);
    }

}

Update: Suggest as per @rnofenko (see comments) made a huge improvement but still seem way to slow? 更新:根据@rnofenko提出的建议(请参阅评论)取得了很大的进步,但似乎仍然很慢?

It's a tricky moment. 这是一个棘手的时刻。 You call extension method Single from System.Linq . 您从System.Linq调用扩展方法Single In fact you load whole collection from DB and select by ID inside your application. 实际上,您是从数据库加载整个集合,然后在应用程序中按ID选择。

Instead you need to use MongoDB extension method - SingleAsync from MongoDB.Driver.Linq . 相反,您需要使用MongoDB扩展方法-MongoDB.Driver.Linq中SingleAsync

public async Task<T> GetById(string id)
{
    return await Collection.SingleAsync(x => x.Id == new ObjectId(id));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM