This overview shows which query operations perform well or badly on large datasets. It should give you an idea which operations can be used on large datasets and which operations can only be applied for small datasets.
For a good query performance fields which are used in a query have to be indexed. Otherwise db4o needs to scan through all objects. With an index these operations should scale logarithmically with the amount of data. The following queries all assume that the fields are indexed.
Simple equals operations on indexed fields’ perform very well.
final Query query = container.query(); query.constrain(Item.class); query.descend("indexedString") .constrain(criteria);
Not equals operations also do perform well. However a 'not equals' operation tends to return a large result which will slow down the query.
final Query query = container.query(); query.constrain(Item.class); query.descend("indexedString") .constrain(criteria).not();
Queries which navigate along references are executed also efficiently, as long every field and reference is indexed.
However there's a catch to this: The reference field type has to be a concrete type. If a field type is a generic type, an interface or an object-type, then the query runs slow.
// Note that the type of the 'indexedReference' has to the specific type // which holds the 'indexedString' final Query query = container.query(); query.constrain(ItemHolder.class); query.descend("indexedReference").descend("indexedString") .constrain(criteria);
Like regular equals operation, comparisons against references also have a good performance.
Item item = loadItemFromDatabase(); final Query query = container.query(); query.constrain(ItemHolder.class); query.descend("indexedReference") .constrain(item);
Comparison and range queries also perform well.
final Query query = container.query(); query.constrain(Item.class); query.descend("indexNumber") .constrain(criteria).greater();
final Query query = container.query(); query.constrain(Item.class); query.descend("indexNumber") .constrain(biggerThanThis).greater().and( query.descend("indexNumber").constrain(smallerThanThis).smaller());
Comparisons on dates also run fast:
final Query query = container.query(); query.constrain(Item.class); query.descend("indexDate") .constrain(date);
final Query query = container.query(); query.constrain(Item.class); query.descend("indexDate") .constrain(date).greater();
Here's an overview of the query operations with bad performances characteristics. The reason is that db4o cannot utilize indexes to perform these queries.That means the query time grows linearly with the amount of data.
Since SODA is the low level query API all other query API will also perform badly for these operations.
When your query navigates across a field which type is a generic parameter, an object or interface then the performance is bad. The reason is that the query engine cannot be sure which objects potentially can be referenced by that field and therefore cannot use the index.
This is not true when the field has a concrete type.
// The type of the 'indexedReference' is the generic parameter 'T'. // Due to type type erasure that type is unknown to db4o final Query query = container.query(); query.constrain(GenericItemHolder.class); query.descend("indexedReference").descend("indexedString") .constrain(criteria);
All string operations beside the simple equals operation cannot use indexes at the moment. Therefore all string operations like contains, like, starts with etc. run slowly.
final Query query = container.query(); query.constrain(Item.class); query.descend("indexedString") .constrain(criteria).contains();
final Query query = container.query(); query.constrain(Item.class); query.descend("indexedString") .constrain(criteria).like();
Any query which does contains operations on collections/arrays or navigates across a collection/array field will run slowly. The reason is that db4o cannot index collections.
final Query query = container.query(); query.constrain(CollectionHolder.class); query.descend("items") .constrain(itemToQueryFor);
final Query query = container.query(); query.constrain(CollectionHolder.class); query.descend("items") .descend("indexedString").constrain(criteria);
db4o does not use indexes for sorting operations. Therefore sorting is not a fast operation. However in most cases a query result is small enough so that the sorting time doesn't consume too much time.
final Query query = container.query(); query.constrain(Item.class); query.descend("indexedString").orderAscending();
Evaluations cannot use indexes and will run slowly.
final Query query = container.query(); query.constrain(Item.class); query.descend("indexedString").constrain(new Evaluation() { @Override public void evaluate(Candidate candidate) { if (candidate.getObject() instanceof String) { String value = (String) candidate.getObject(); if (value.matches("abc")) { candidate.include(true); } } } });
The best indication that a query is slow is when it cannot use any field index. Install a diagnostic listener and look for the LoadedFromClassIndex message. That message indicates that a query couldn't use any field index for its execution.