2012-09-07 4 views
0

OutOfMemoryError caused when db4o databse has 15000+ objectsComment augmenter la vitesse de requête dans db4o?

Ma question fait référence à ma question précédente (ci-dessus). Pour le même modèle PostMessage et la même requête.

Avec 100 000 objets MessageMessage, la requête prend environ 1243 ms pour renvoyer les 20 premiers messages envoyés. Maintenant, j'ai sauvé 1 000 000 objets de MessageMessage dans DB4O. La même requête a pris 342 132 ms. Ce qui est non linéaire haut.

Comment puis-je optimiser la vitesse de requête?

FYR: Les champs timeSent et timeReceived sont des champs indexés. J'utilise le mode de requête SNAPSHOT. Je n'utilise pas TA/TP.

+0

Vous dites que vous voulez juste le «20 premiers», est l'information que vous utilisez pour commander les résultats indexés dans la DB? – paul

+0

Oui, il est indexé. Je n'utilise pas le TA/TP. J'utilise le mode de requête SNAPSHOT. Et 20 premiers, c'est parce que je veux accéder aux messages publiés de manière paginée. –

+0

Est-ce que Gamlor peut commenter sur celui-ci? –

Répondre

0

Triez-vous le résultat? Malheureusement, db4o n'utilise pas l'index pour trier/orderBy. Cela signifie qu'il exécutera un algorithme de tri normal, avec O (n * log (n)). Il ne sera pas scala liniearly.

De même, db4o ne prend pas en charge un opérateur TOP. Cela signifie que même sans tri, il faut un peu de temps pour copier les identifiants dans le jeu de résultats, même si vous ne lisez jamais les entités par la suite. Donc, il n'y a pas vraiment de bonne solution pour cela, sauf essayer d'utiliser certains critères qui réduisent la taille du résultat.

Certains adventerous pourraient utiliser un query evaluation différent, mais personnellement ne le recommande pas.

0

@Gamlor Non, je ne trie pas du tout. Le code est le suivant:

public static ObjectSet<PostedMessage> getMessagesBetweenDates(
     Calendar after, 
     Calendar before, 
     ObjectContainer db) { 

    if (after == null || before == null || db == null) { 
     return null; 
    } 
    Query q = db.query(); //db is pre-configured to use SNAPSHOT mode. 
    q.constrain(PostedMessage.class); 
    Constraint from = q.descend("timeRecieved").constrain(new Long(after.getTimeInMillis())).greater().equal(); 
    q.descend("timeRecieved").constrain(new Long(before.getTimeInMillis())).smaller().equal().and(from); 
    ObjectSet<EmailMessage> results = q.execute(); 
    return results; 
} 

Les arguments de cette méthode sont les suivantes:

après = 13.09.2011 10:55:55

avant = 10 13-09-2011 : 56: 10

Et je m'attends à ce que seulement 10 messages envoyés soient retournés entre "après" et "avant". (Je génère MessageMessage factice avec timeReceived incrémenté de 1 sec chacun.)

Questions connexes