我有大量的 LiteDB 项目集合。我只想找到按某些标准添加的最后一个。标准在 lambda 表达式中。我的问题是,它花了很长时间(现在大约 2-3 秒),而我只有测试数据库。在完整模式下,值将增加 10 倍。
我现在的代码,带有时间戳:
var values = db.GetCollection<ExtendedValue>(IncomingValueCollection);
if (values.Count() > 0) {
Stopwatch sw = new Stopwatch();
sw.Reset();
sw.Start();
var expressedVals = values.Find(lambda);
sw.Stop();
Debug.WriteLine("find values " + sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
var inOrder = expressedVals.OrderByDescending(x => x.TimeCaptured).Take(5);
sw.Stop();
Debug.WriteLine("order " + sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
var result = inOrder.First();
sw.Stop();
Debug.WriteLine("last " + sw.ElapsedMilliseconds);
return result;
//withouth stopwatch
//return values.Find(lambda).OrderByDescending(x => x.TimeCaptured).First();
}
结果是:
find values 0
order 0
last 2399
所以很明显,选择值需要大部分时间。
我努力了:
- 只需在orderedEnum上使用.First(),没有变化
- 使用 Take( x ) 与否,没有变化
- 将其转换为数组或列表,然后选择第一个,这需要更长的时间,但没什么意义
我认为, .First() 从枚举创建数组,然后选择第一项。有没有办法在不生成整个数组并造成大滞后的情况下选择项目?
编辑: 根据 Matthew Watson 的评论,我编辑了代码,发现我的 lambda 表达式花费了大部分时间和结论,First() 方法花费了大部分时间是错误的。它只需要因为它一次执行整个查询。
if (values.Count() > 0) {
Stopwatch sw = new Stopwatch();
sw.Reset();
sw.Start();
var expressedVals = values.Find(lambda).ToList();
sw.Stop();
Debug.WriteLine("find values " + sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
var inOrder = expressedVals.OrderByDescending(x => x.TimeCaptured).ToList();
sw.Stop();
Debug.WriteLine("order " + sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
var result = expressedVals.First();
sw.Stop();
Debug.WriteLine("last " + sw.ElapsedMilliseconds);
return result;
//withouth stopwatch
//return values.Find(lambda).OrderByDescending(x => x.TimeCaptured).First();
结果
find values 2395
order 4
last 0
所以我认为,我不能这样做,我必须创建解决方法。