防止不必要的db命中(Kohana ORM)

时间:2011-02-27 19:00:04

标签: php orm kohana

默认情况下,Kohana的ORM在识别已加载的对象时并不像我想的那么聪明。它保存通过关系加载的对象,例如:

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

但是,如果找到bar的方法不止一种,那就不会发现它。假设foothing(我们需要更多元语法变量)与同一bar有关系:

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

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

我试图通过模型和id键入预加载的对象数组来解决这个问题。它有效,但问题是它只有在我提前知道ID时才有效。我重载的ORM函数如下所示:

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;
}

这样做的目的是,如果我在两个不同的地方访问同一个对象,并且它们有可能是同一个对象,那么它不会错误地半更新两个不同的实例,而是正确更新一个预先加载的实例实例

在我通过主键之外的其他东西找到对象的情况下,上述find方法不必要地命中DB。有什么我可以做的,以防止这种情况,而不是按照每个可以想象的标准键入预加载的对象?这里的核心问题看起来非常基本,我很惊讶它不是原始ORM库的一部分。有没有理由,或者我忽略了什么?大多数人做了什么来解决这个问题或绕过它?无论解决方案是什么,当我将memcache集成到我的代码中时,我将进一步应用它,因此可能有助于牢记这一点。

1 个答案:

答案 0 :(得分:1)

config/database.php中启用每请求数据库缓存('缓存'参数,默认情况下为FALSE)。这将允许您对相同的查询使用缓存结果。