我在我的数据库中存储了 30,000 个 SimpleObjects:
class SimpleObject
{
public int Id { get; set; }
}
我想在 DB4O 上运行一个查询,以查找具有任何指定 ID 的所有 SimpleObjects:
public IEnumerable<SimpleObject> GetMatches(int[] matchingIds)
{
// OH NOOOOOOES! This activates all 30,000 SimpleObjects. TOO SLOW!
var query = from SimpleObject simple in db
join id in matchingIds on simple.Id equals id
select simple;
return query.ToArray();
}
如何编写此查询以使 DB4O 不激活所有 30,000 个对象?
最佳答案
我不是这方面的专家,在 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 私有(private)字段而不是属性。性能要好得多,约为 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 字段查询的代码也不难包装成更通用的代码。
关于c# - db4o 查询 : find all objects with ID = {anything in array},我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1689089/