【问题标题】:OutOfMemoryError caused when db4o database has 15000+ objects当 db4o 数据库有 15000+ 个对象时导致 OutOfMemoryError
【发布时间】:2012-08-21 23:29:55
【问题描述】:

我正在使用 db4o 8.0。

我有课

PostedMessage{
    @Indexed
    long receivedTime;
    @Indexed
    long sentTime;
    ...    
    //getter methods and setter methods for all the fields.
}

我将 PostedMessage 对象持久保存到 db4o 数据库。我已经将 15000 多个对象保存到 db4o 数据库。现在,当我运行以下查询时,它会导致 OutOfMemoryError。

    //Query to get PostedMessages between "start" and "end" dates.
    Query q = db.query();
    q.constrain(PostedMessage.class);
    Constraint from = q.descend("receivedTime").constrain(new Long(start.getTimeInMillis())).greater().equal();
    q.descend("receivedTime").constrain(new Long(end.getTimeInMillis())).smaller().equal().and(from);
    q.execute();//results in OutOfMemoryError

为了避免 OutOfMemoryError,我需要为 PostedMessage 类的字段添加索引。 Read This

我有一个服务器/客户端配置。在打开 ObjectContainer 之前,我无法控制它的预配置。

在 ObjectContainer 刚刚打开并提供给我之后,我必须应用/附加索引 CommonConfiguration。

我知道如何创建配置。

    EmbeddedConfiguration appendConfig = Db4oEmbedded.newConfiguration();
    appendConfig.common().objectClass(EmailMessage.class).objectField("receivedTime").indexed(true);
    appendConfig.common().objectClass(EmailMessage.class).objectField("sentTime").indexed(true);

我无法弄清楚如何将此配置应用于已打开的 ObjectContainer。 如何为刚刚打开的 ObjectContainer 添加索引?

EmbeddedConfigurationItem 的 apply() 方法是答案吗?如果是,我可以得到一个示例代码来说明如何使用它吗?

已编辑:稍后在问题中添加了 @Indexed 注释。

【问题讨论】:

    标签: java db4o


    【解决方案1】:

    【讨论】:

    • 我们在服务器中创建一个预先建立的连接队列(即 ObjectContainers)。并根据需要获取连接。我的问题是,我可以将新的索引配置应用于这些预先打开的 ObjectContainers 吗?
    • 再输入一个。我有客户端/服务器配置。我刚刚读到“您还应该确保客户端和服务器都使用相同的配置设置”。是否影响索引相关配置?
    • 看Gamlor的评论在http://stackoverflow.com/questions/4370062/do-i-have-to-re-apply-db4o-configuration-settings-and-indexes-on-each-申请
    • 我添加了@Indexed 注释。但是,当有 100000 个 PostedMessage 对象时,它仍然会导致 OutOfMemoryError。
    • 您还必须安装透明激活/透明持久性以避免在内存中加载不必要的对象。看教程中的第10&11章(在下载的db4o[Version].zip的doc/tutorial目录下]
    【解决方案2】:

    cl-r 关于使用 TA/TP 的建议对我来说就像一个魅力。见他上面的评论。

    您还必须安装透明激活/透明 持久性以避免在内存中加载不必要的对象。看着 教程中的第 10 章和第 11 章(在 doc/tutorial 目录中) 下载的db4o[版本].zip] - cl-r

    【讨论】:

    • 1 个更合理的解决方案。使用 IMMEDIATE 和 SNAPSHOT 查询模式。
    • 如果你不使用TA/TP,那些查询模式选项总是可以加载内存中的所有数据库,所以你可以使用TA/TP+查询模式作为方便。 -附言通常,您现在可以投票了。
    【解决方案3】:

    在我的特殊情况下,我需要遍历查询返回的 ObjectSet。

    发现使用IMMEDIATE和SNAPSHOT查询​​方式也解决了OutOfMemoryError问题。时机也同样好。 LAZY 模式不是我的解决方案。

    从已保存的 100000 条 PostedMessage 中检索任意 100 条 PostedMessage 大约需要 8000 到 9000 毫秒。例如1 到 100、1001 到 1100、99899 到 99999。

    【讨论】:

      【解决方案4】:

      您应该为查询添加索引。否则 db4o 必须扫描所有对象。

      您可以使用注释来做到这一点,如下所示:

      import com.db4o.config.annotations.Indexed;
      
      PostedMessage{
          @Indexed
          long receivedTime;
          long sentTime;
      

      或者像你一样,使用配置:

      EmbeddedConfiguration config = Db4oEmbedded.newConfiguration();
      config.common().objectClass(EmailMessage.class).objectField("receivedTime").indexed(true);
      config.common().objectClass(EmailMessage.class).objectField("sentTime").indexed(true);
      ObjectContainer container = Db4oEmbedded.openFile(config,"your-data.db4o");
      

      当容器已在运行时,您无法添加此配置。只有打开的时候。当索引尚不存在时,将在打开数据库时添加它们。打开时,您需要控制它。或者使用上面的注解。

      【讨论】:

      • 我使用了@Indexed注解。
      • 嗯...不知道更多...你给了多少内存?我没有其他想法。不看运行示例就想不出任何解决方案
      • 好了,这个问题解决了。我能够保存 15000 个 PostedMessage 对象。使用 15000 个对象进行查询也非常快。在给定的 DateTime 之后,获取 10 个 PostedMessage 大约需要 1030 毫秒。现在我面临 300000 个对象的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-07
      • 2011-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-18
      • 1970-01-01
      相关资源
      最近更新 更多