我不是这方面的专家,在 DB4O 论坛上发帖可能会很好,但我想我有一个解决方案。它涉及不使用 LINQ 和使用 SODA。
这就是我所做的。我创建了一个快速项目,根据您的帖子定义使用 30000 SimpleObject 填充数据库。然后我编写了一个查询来从数据库中获取所有 SimpleObjects:
var simpleObjects = db.Query<SimpleObject>(typeof(SimpleObject));
当我用秒表包裹它时,运行大约需要 740 毫秒。然后,我使用您的代码搜索 0 到 2999 之间的 100 个随机数。响应为 772 毫秒,因此基于该数字,我假设它将所有对象从数据库中拉出。我不确定如何验证这一点,但后来我想我用性能证明了这一点。
然后我往下走。据我了解,DB4O 团队的 LINQ 提供者只是将其转换为 SODA。因此,我想我会编写一个 SODA 查询来测试,我发现对属性使用 SODA 对性能不利,因为它需要 19902 毫秒才能执行。这是代码:
private SimpleObject[] GetSimpleObjectUsingSodaAgainstAProperty(int[] matchingIds, IObjectContainer db)
{
SimpleObject[] returnValue = new SimpleObject[matchingIds.Length];
for (int counter = 0; counter < matchingIds.Length; counter++)
{
var query = db.Query();
query.Constrain(typeof(SimpleObject));
query.Descend("Id").Constrain(matchingIds[counter]);
IObjectSet queryResult = query.Execute();
if (queryResult.Count == 1)
returnValue[counter] = (SimpleObject)queryResult[0];
}
return returnValue;
}
因此,考虑到为什么会如此糟糕,我决定不使用自动实现的属性并自己定义它,因为属性实际上是方法而不是值:
public class SimpleObject
{
private int _id;
public int Id {
get
{ return _id; }
set
{ _id = value; }
}
}
然后我重写了查询以使用 _id 私有字段而不是属性。在大约 91 毫秒时,性能要好得多。这是该代码:
private SimpleObject[] GetSimpleObjectUsingSodaAgainstAField(int[] matchingIds, IObjectContainer db)
{
SimpleObject[] returnValue = new SimpleObject[matchingIds.Length];
for (int counter = 0; counter < matchingIds.Length; counter++)
{
var query = db.Query();
query.Constrain(typeof(SimpleObject));
query.Descend("_id").Constrain(matchingIds[counter]);
IObjectSet queryResult = query.Execute();
if (queryResult.Count == 1)
returnValue[counter] = (SimpleObject)queryResult[0];
}
return returnValue;
}
为了确保这不是侥幸,我运行了几次测试并收到了类似的结果。然后我又添加了 60,000 条记录,总共 90,000 条,这就是性能差异:
GetAll: 2450 ms
GetWithOriginalCode: 2694 ms
GetWithSODAandProperty: 75373 ms
GetWithSODAandField: 77 ms
希望有帮助。我知道它并不能真正解释原因,但这可能有助于解决方法。SODA 字段查询的代码也不难包装成更通用的代码。