防止不必要的数据库点击 (Kohana ORM)

发布于 2024-10-19 05:43:58 字数 1490 浏览 1 评论 0原文

默认情况下,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;
}

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

当我通过主键以外的其他方式找到对象时,上面的查找方法不必要地访问数据库。除了按照每一个可以想象的标准对预加载的对象进行键入之外,我还能做些什么来防止这种情况发生吗?这里的核心问题看起来非常基本,以至于我很惊讶它不是原始 ORM 库的一部分。这是有原因的,还是我忽略了什么?大多数人会做什么来解决或绕过这个问题?无论解决方案是什么,当我将 memcache 集成到我的代码中时,我都会进一步应用它,因此记住这一点可能会有所帮助。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小清晰的声音 2024-10-26 05:43:58

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文