简体   繁体   中英

Preventing unnecessary db hits (Kohana ORM)

Kohana's ORM, by default, is not as smart as I wanted when it comes to recognizing which objects it has already loaded. It saves objects loaded through a relationship, for example:

$obj = $foo->bar;    // hits the DB for bar
/* ... Later ... */
$obj = $foo->bar;    // had bar preloaded, so uses that instead

But if there's more than one way to find bar , it doesn't see that. Let's say both foo and thing (we need more meta-syntactic variables) have a relationship with the same bar :

$obj = $foo->bar;    // hits DB

$obj = $thing->bar   // hits DB again, even though it's the same object

I've attempted to fix this by having a preloaded array of objects keyed by model and id. It works, but the problem is that it only works if I know the ID ahead of time. My overloaded ORM functions look like this:

public function find($id = NULL)
{
    $model = strtolower(get_class($this));

    if ($id != NULL)   // notice I don't have to hit the db if it's preloaded.
    {
        $key = $model . '_' . $id;
        if (array_key_exists($key, self::$preloaded)) return self::$preloaded[$key];
    }

    $obj = parent::find($id);
    $key = $model . '_' . $obj->pk();

    // here, I have to hit the DB even if it was preloaded, just to find the ID!
    if (array_key_exists($key, self::$preloaded)) return self::$preloaded[$key];

    self::$preloaded[$key] = $obj;
    return $obj;
}

The purpose of this is so that if I access the same object in two different places, and there's a chance they're the same object, it won't incorrectly half-update two different instances, but correctly update the one preloaded instance.

The above find method hits the DB needlessly in cases where I find an object by something other than primary key. Is there anything I can do to prevent that, short of keying the preloaded objects by every imaginable criterion? The core issue here seems so basic that I'm surprised it's not part of the original ORM library. Is there a reason for that, or something I overlooked? What do most people do to solve this or get around it? Whatever the solution is, I'll be applying it further when I integrate memcache into my code, so it might help to keep that in mind.

Turn on per-request DB caching in config/database.php ('caching' param, its FALSE by default). This will allow you to use cached results for the same queries.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM