我有一组从Class::DBI继承的相当复杂的 ORM 模块。由于数据很少更改,我正在考虑在此之上使用缓存/记忆层来加快速度。我找到了一个模块:Class::DBI::Cacheable但没有评级或对 RT 的任何评论。我希望收到使用过这个或任何其他 Class::DBI 缓存方案的人的来信。
万分感谢。
我有一组从Class::DBI继承的相当复杂的 ORM 模块。由于数据很少更改,我正在考虑在此之上使用缓存/记忆层来加快速度。我找到了一个模块:Class::DBI::Cacheable但没有评级或对 RT 的任何评论。我希望收到使用过这个或任何其他 Class::DBI 缓存方案的人的来信。
万分感谢。
我也滚动了很多次我不想说的 ORM!如果您的所有提取都通过单个 api(或其子类)发生,那么缓存/记忆化非常容易。
对于基于唯一键的任何获取,您可以仅基于键的串联进行缓存。一种天真的方法可能是:
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
}
您可以使用 CPAN 上的 Cache:: 模块套件代替散列,在缓存中实现时间和内存限制。
如果您要缓存一段时间,您可能需要考虑一种使缓存中的对象过期的方法。例如,如果您的所有更新也通过 ORM,您可以在 update() ORM 方法中清除(或更新)缓存条目。
最后一点要仔细考虑 - 您每次都返回相同的对象,这会产生影响。例如,如果一段代码检索了一个对象并更新了一个值,但没有将该更改提交到数据库,则检索该对象的所有其他代码都将看到该更改。如果您将一系列操作串在一起,这将非常有用——它们都可以更新对象,然后你可以在最后提交它——但这可能不是你想要的。我通常在对象从数据库中更新时在对象上设置一个标志,然后在您的 setter 方法中,如果对象已更新,则使该标志无效 - 这样,如果您真的想要一个新对象,您始终可以检查该标志。
有几次我们推出了自己的,但我们将其限制在分析表明我们需要提升的特殊情况(例如大型连接)。由于我们的应用程序通常在数据库访问之上使用自定义抽象层(类似于本土 ORM),这就是我们实现缓存的地方。我们取得了令我们满意的好成绩,而且没有付出太多努力。当然,由于我们没有使用 CPAN ORM,我们也没有任何选择使用 CPAN 缓存模块。
这是严格逐案和选择加入的。无论您最终是使用 CPAN 解决方案还是自己使用 CPAN 解决方案,最好将其限制在分析表明您需要帮助的情况下,并确保它是可选的,这样您的缓存就不会以微妙的方式破坏您的应用程序在你没想到的时候积极主动。