tags:

views:

313

answers:

2

Hi there,

I'm attempting to use db4o as the back-end for my new website.

I've set things up, as I thought sensible, and have inserted about 5k records (of only one object type, with about 7 primitive fields).

As per some blog posts I've read, I've setup the properties as non-automatic properties, and tried to set indexes on the private members exposed by the public properties.

Query performance is really bad, with what should be a simple indexed lookup taking upto 3/4 seconds.

My implementation is a follows: My 'Server' is a static singleton, only opened once per application instance.

Db4oFactory.Configure().ObjectClass(typeof(MyObject)).ObjectField("_Id").Indexed(true);
server = Db4oClientServer.OpenServer("DatabseName", 0);

then, to query:

using (var ooDB = server.OpenClient())
{
    var movieFound = (from MyObject m in ooDB
                    where m.Id == IdToFind
                    select m).FirstOrDefault();
}

With my object as:

public class MyObject
{
    protected string _Id;
    public string Id 
    { 
        get { return _Id; } 
        set { _Id = value; } 
    }
}

The Object's Id is a string.

What am I doing wrong!

Cheers, Dave

A: 

I haven't used db4o for a while, but what strikes me here is that you query the property and create an index on the backing field. Unless db4o manages to understand the relationship (it might, but I doubt it for now) it's going to revive every stored instance to access the property and evaluate your query..

Can you link to the posts that asked for this kind of setup for the indices?

Benjamin Podszun
Actually the db4o-LINQ implementation finds out the field behind a property.
Gamlor
+2  A: 

This is a case of an unlucky combination of the old API (version 7.4, still here for compatibility) and new API (version 7.12). The configuration isn't used, so no index is created.

The method call 'Db4oFactory.Configure()' belongs to the older API. It is only used when you create an ObjectContainer with the old API: 'Db4oFactory.OpenServer()'. This global configuration has some potential problem. So I would avoid it.

Now I recommend to use the new API. There you have to pass the configuration explicit. Also the configuration interface is more clean. Especially is the client/server configuration separated. Use 'Db4oClientServer.NewServerConfiguration()' to create a new configuration. And then pass it to 'Db4oClientServer.OpenServer'. So in your case this would be:

        IServerConfiguration cfg = Db4oClientServer.NewServerConfiguration();
        cfg.Common.ObjectClass(typeof(MyObject)).ObjectField("_Id").Indexed(true);

        IObjectServer server = Db4oClientServer.OpenServer(cfg, "DatabseName.db4o", 0);
Gamlor
Hi there,I followed your advice, but spoke too soon, I think.I thought I had gained the improved performance from the indexes working correctly - however I this was just due to the fact that I truncated my database - as soon as the number of items approaches a few thousand, the query time increases exponentially - indicating to me that the indexes aren't being used.
Dave
Hi, it should work. You can configure a diagnostig-listener. So you can see if the index is used: 'cfg.Common.Diagnostic.AddListener(new DiagnosticToConsole())'. Be aware that to first LINQ-query takes way longer, because the db4o-LINQ-system has to be initialized etc. I my examples the index is used for the query. With 20'000 simple object it takes about 4-5 milliseconds. Without index around 300 milliseconds. Anyway I've uploaded the source-code. So you can check if it works on your machine: http://www.gamlor.info/files/dotNet/IndexOnStringField.cs
Gamlor