1

I am using db4o 8.0.

I have a class

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

I persist the PostedMessage objects to db4o database. I have already saved 15000+ objects to db4o database. And now when I run following query, it results in 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

To avoid the OutOfMemoryError, I need to add indexes to the fields of PostedMessage class. Read This.

I have a server/client configuration. I don't have control over pre-configuring the ObjectContainer before opening it.

I will have to apply/append the indexing CommonConfiguration after the ObjectContainer is just opened and provided to me.

I know how to create the config.

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

I am not able to figure out how to apply this config to already opened ObjectContainer. How can I add indexes to the just opened ObjectContainer?

Is EmbeddedConfigurationItem's apply() method the answer? If it is, can I get a sample code that shows how to use it?

Edited : Added @Indexed annotation later to the question.

batman567
  • 826
  • 2
  • 12
  • 23

4 Answers4

1

Look in Reference doc at @Indexed

cl-r
  • 1,264
  • 1
  • 12
  • 26
  • We create a queue of pre-made connections (i.e. ObjectContainers) in the server. And acquire the connections as needed. My question is, can I apply new configuration of index to such pre-opened ObjectContainers ? – You Help Me Help You Aug 30 '12 at 11:01
  • One more input. I have client/server configuration. And I just read that "you should also ensure that both client and server use the same configuration settings". Does it affect the indexing related configuration? – You Help Me Help You Aug 30 '12 at 11:12
  • Look at Gamlor's comment inhttp://stackoverflow.com/questions/4370062/do-i-have-to-re-apply-db4o-configuration-settings-and-indexes-on-each-applicat – cl-r Aug 30 '12 at 11:52
  • I added @Indexed annotation. However, it still is causing OutOfMemoryError when there are 100000 PostedMessage objects. – You Help Me Help You Aug 30 '12 at 12:17
  • You have also to install Transparent Activation/Transparent Persistence to avoid to load unnecessary object in memmory. Look at chapter 10&11 in tutorial (in the doc/tutorial directory of the downloaded db4o[Version].zip] – cl-r Aug 30 '12 at 13:14
  • My primary concern is to avoid OutOfMemoryError while executing the simple query mentioned in my question. – You Help Me Help You Aug 30 '12 at 13:23
  • But if you do not take care of depth problem, you can load all you container in memory. TA/TP is a perfect and secure tool to avoid this – cl-r Aug 30 '12 at 13:37
  • I am afraid that my SODA query is not using the indexed fields (namely receivedTime & sentTime), despite adding @Indexed annotation. If my SODA query uses field indexes, it should have no reason of activating the (Candidate) PostedMessage objects. But let me try the TA first and see if that helps. – You Help Me Help You Aug 30 '12 at 14:40
  • Is db4oTool.exe meant only for .net or can it be used for java too? http://community.versant.com/documentation/reference/db4o-7.12/net2/reference/Content/implementation_strategies/enhancement_tools/enhancement_for_.net/db4otool.html – You Help Me Help You Aug 30 '12 at 17:39
  • Thanks cl-r. Your suggestion of TA/TP worked like a charm for me. – You Help Me Help You Aug 30 '12 at 20:27
  • Before implementing TA/TP the timings of the query were horrible. A simple query would take 768000 ms. Now. the same query takes about 7000 ms on a database (of size 156MB) containing 100000 PostedMessage objects. – You Help Me Help You Aug 30 '12 at 20:28
  • You have to use LAZY query to begin your work berfore all selected instances are load in memory, but the fastest way is to add also index the field you want in configuration (client [AND sever if you use it]) – cl-r Aug 31 '12 at 06:57
0

cl-r's suggestion of using TA/TP worked like a charm in my case. See his comment above.

You have also to install Transparent Activation/Transparent Persistence to avoid to load unnecessary object in memmory. Look at chapter 10&11 in tutorial (in the doc/tutorial directory of the downloaded db4o[Version].zip] - cl-r

  • http://meta.stackexchange.com/questions/79347/reminding-new-users-of-accept-upvote-duty – cl-r Aug 31 '12 at 06:54
  • 1 more plausible solution. Use the IMMEDIATE and SNAPSHOT Query Modes. – You Help Me Help You Sep 04 '12 at 06:34
  • 1
    If you do not use TA/TP, those query mode options can always load all the database in memory, so you can use TA/TP + query mode as convenient. - P.S. Normally, you can now upvote. – cl-r Sep 04 '12 at 08:34
0

In my particular case, I need to iterate over the ObjectSet returned by the query.

It was found that using IMMEDIATE and SNAPSHOT query modes also solved the OutOfMemoryError problem. Also the timings were equally well. LAZY mode is not the solution for me.

It took about 8000 to 9000 ms to retrieve any 100 PostedMessages out of 100000 saved PostedMessages. e.g. 1 to 100, 1001 to 1100, 99899 to 99999.

0

You should add indexes for your queries. Otherwise db4o has to scan over all objects.

You can do it with an annotation, like this:

import com.db4o.config.annotations.Indexed;

PostedMessage{
    @Indexed
    long receivedTime;
    long sentTime;

Or as you do, with the configuration:

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");

You cannot add this configuration when the container is already running. Only when opening it. When the indexes are not there yet, they will be added while opening the database. You need to get control over it, when opening. Or use the annotation above.

Gamlor
  • 12,978
  • 7
  • 43
  • 70
  • I have used the @Indexed annotations. – You Help Me Help You Sep 13 '12 at 11:38
  • Hmm...don't know more...how much memory do you give? I've no other idea from the top of my head. Can't come up with any solution, without looking at a running example – Gamlor Sep 13 '12 at 11:42
  • Well, this question is solved. I am able to save 15000 PostedMessage ojects. Querying is also pretty fast with 15000 objects. It takes about 1030 ms to fetch 10 PostedMessages after given DateTime. Now I am facing problem at 300000 objects now. – You Help Me Help You Sep 13 '12 at 14:28