Réduire le nombre d'accès à la base de données lors de la récupération d'enregistrementsen profitant du cache des modèles

Le framework ICanBoogie utilise le patron de conception ActiveRecord pour la gestion de ses enregistrements. Chaque enregistrement en base de données est représenté par un objet instancié d'une classe. Afin de garantir la validité des données de l'instance, l'enjeu pour le framework est de retourner la même instance lorsqu'elle est demandée à divers endroits de l'application. En effet, on ne voudrait pas qu'un même enregistrement récupéré à divers endroits de l'application, puis modifié de façon différente puis enregistré à divers moment ne perde ses différents états.

Différentes manières de charger un ou plusieurs enregistrements

Il existe différentes manières de charger un ou plusieurs enregistrements, selon que l'on utilise leur identifiant ou que l'on utilise des conditions :

<?php

$record = $model->find(6)// récupère l'enregistrement avec la clé primaire 6
$records = $model->find(6789)// récupère les enregistrements avec les clés primaires 6, 7, 8 et 9

$record = $model->where(array('id' => 6))->one// récupère l'enregistrement avec la clé primaire 6
$records = $model->where(array('id' => array(6789))->all// récupère les enregistrements avec les clés primaires 6, 7, 8 et 9

Que l'on utilise la méthode find() ou une requête on obtiendra le même résultat, à savoir l'enregistrement 6 et un tableau associatif avec les enregistrements 6, 7, 8 et 9. Il y a pourtant une différence essentielle entre ces résultats.

L'instance de l'enregistrement 6 retournée dans le tableau associatif par la méthode find() est la même que celle retournée lorsque l'enregistrement avait été récupéré seul.

<?php

$record = $model->find(6);
$records = $model->find(6789);

echo $record === $records[6] ? "la même !" : "pas la même :-("
// => "la même !"

Ce qui n'est pas le cas des instances récupérées en utilisant des conditions :

<?php

$record = $model->where(array('id' => 6))->one;
$records = $model->where(array('id' => array(6789))->all;

foreach ($records as $r)
{
    if ($r->id != 6}
    {
        continue;
    }

    echo $record === $r ? "la même !" : "pas la même :-("
    // => "pas la même :-("
}

Réutilisation des instances

Les instances récupérées par la méthode find() sont mises en cache et son réutilisées lorsqu'elles sont à nouveau demandées. Lors du second appel, seules les instances absentes du cache sont chargées, à savoir 7, 8 et 9. Si on demandait à nouveau les enregistrements avec les clés primaires 6, 7, 8 et 9 on obtiendrait les mêmes instances et on économiserait un appel SQL.

Conclusion

Comme les instances récupérées avec la méthode find() sont toujours les mêmes, elles peuvent être utilisées et modifiées sans problèmes dans l'ensemble de l'application. Le cadeau bonus c'est qu'une instance demandée un milliard de fois ne coutera qu'un appel à la base de données. Le second cadeau bonus c'est que si APC est activé les instances persistent d'une session à l'autre, évitant autant de passage par la base de données.

Laisser un commentaire

Pas de commentaire