2009-04-16 13 views
3

J'ai un ensemble de modules ORM plutôt complexes qui héritent de Class::DBI. Comme les données changent assez rarement, j'utilise une couche Caching/Memoization pour accélérer les choses. J'ai trouvé un module: Class::DBI::Cacheable mais aucune évaluation ni d'avis sur RT. J'apprécierais d'entendre des personnes qui ont utilisé ceci ou n'importe quel autre schéma de mise en cache de Class :: DBI.Existe-t-il un moyen de mettre en cache un mécanisme pour Class :: DBI?

Merci beaucoup.

Répondre

3

J'ai aussi roulé mon propre ORM beaucoup de fois que je déteste dire! La mise en cache/mémorisation est assez facile si toutes vos récupérations se font par le biais d'une seule API (ou de ses sous-classes).

Pour toute récupération basée sur une clé unique, vous pouvez simplement mettre en cache en fonction d'une concaténation des clés. Une approche naïve pourrait être:

my %_cache; 

sub get_object_from_db { 
    my ($self, $table, %table_lookup_key) = @_; 

    # concatenate a unique key for this object 
    my $cache_key = join('|', map { "$_|$table_lookup_key{$_}" } 
         sort keys %table_lookup_key 

    return $_cache{$cache_key} 
     if exists $_cache{$cache_key}; 

    # otherwise get the object from the db and cache it in the hash 
    # before returning 
} 

Au lieu d'un hachage, vous pouvez utiliser le cache :: suite de modules sur CPAN pour respecter des délais et de la mémoire dans le cache.

Si vous souhaitez mettre en cache pendant un certain temps, vous pouvez envisager d'expirer des objets dans le cache. Si, par exemple, toutes vos mises à jour passent également par l'ORM, vous pouvez effacer (ou mettre à jour) l'entrée de cache dans votre méthode ORM update(). Un dernier point à considérer avec attention - vous renvoyez le même objet à chaque fois, ce qui a des implications. Si, par exemple, un morceau de code récupère un objet et met à jour une valeur mais ne valide pas cette modification sur la base de données, tous les autres codes récupérant cet objet verront cette modification. Cela peut être très utile si vous enchaînez une série d'opérations - ils peuvent tous mettre à jour l'objet et ensuite vous pouvez le valider à la fin - mais ce n'est peut-être pas ce que vous voulez. Je place habituellement un drapeau sur l'objet quand il est frais de la base de données et puis dans votre méthode de setter invalide cet indicateur si l'objet est mis à jour - de cette façon vous pouvez toujours vérifier ce drapeau si vous voulez vraiment un nouvel objet.

2

À quelques reprises, nous avons roulé les nôtres, mais nous l'avons limité à des cas particuliers où le profilage indiquait que nous avions besoin d'un coup de pouce (par exemple, de grosses jointures). Étant donné que nos applications utilisent généralement une couche d'abstraction personnalisée (semblable à un ORM développé localement) au-dessus de l'accès DB, c'est là que nous avons implémenté la mise en cache. Nous avons obtenu de bons résultats dont nous étions satisfaits et cela n'a pas demandé beaucoup d'efforts. Bien sûr, puisque nous n'utilisions pas un ORM CPAN, nous n'avions pas vraiment le choix d'utiliser un module de mise en cache CPAN.

C'était strictement au cas par cas et opt-in. Que vous finissiez par utiliser une solution CPAN ou que vous utilisiez la solution CPAN, il est probablement préférable de la restreindre aux cas où le profilage indique que vous avez besoin d'aide et assurez-vous que cette option est désactivée. en étant actif quand vous ne l'attendiez pas.