c# - db4o 查询 : find all objects with ID = {anything in array}

标签 c# linq db4o

我在我的数据库中存储了 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/

相关文章:

c# - 在 Expression<Func<TModel, Object>> 中评估参数结果

linq - Lambda 查询按日期对列表进行反向排序

c# - 基本的 db4o 问题

Java类对象加密/解密和对象数据库

android - 在 Android 开发中何时选择 DB4o 而不是 SQLite

c# - 在 Visual Studio 中调试 .dll 会终止附加的 Excel session

c# - RavenDB 自动 tmpindex 和手动索引

c# - 我可以在没有存储帐户的情况下使用带有 HTTP 触发器的 Azure Function 吗

javascript - 如何解绑特定页面的脚本

c# - Entity Framework 存储库模式继承