db4o数据库具有15000+个对象时导致的OutOfMemoryError

时间:2012-08-27 13:10:21

标签: java db4o

我正在使用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注释。

4 个答案:

答案 0 :(得分:1)

查看 Reference doc @Indexed

答案 1 :(得分:0)

在我的案例中,cl-r建议使用TA / TP就像一个魅力。见上面他的评论。

  

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

答案 2 :(得分:0)

在我的特定情况下,我需要迭代查询返回的ObjectSet。

发现使用IMMEDIATE和SNAPSHOT查询​​模式也解决了OutOfMemoryError问题。时间也一样好。 LAZY模式对我来说不是解决方案。

从100000个已保存的PostedMessages中检索任何100个PostedMessages需要大约8000到9000毫秒。例如1至100,1001至1100,99899至99999。

答案 3 :(得分:0)

您应该为查询添加索引。否则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");

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