DBICでの簡単キャッシング

DBICで簡単にお金が借りることができます(ちが

まあ、面白くないのでやめておきますが、DBIC
かなりパフォーマンスに気を使った設計なのは周知の事実なのでつが、

キャッシュを使うことでよりパフォーマンス向上が図れます。

例えば

my $itr = $self->model('Member')->search({},{});
while (my $member = $itr->next) {
    warn $member->id;
}
$itr->reset;
while (my $member = $itr->next) {
    warn $member->id;
}

こんな感じの処理があったとします。
Memberテーブルを二度処理するみたいな。


ちなみに同じオブジェクトを使う時は
$itr->reset;
こうしてやればイテレータがリセットされます。


この場合、2個のwhileのところでそれぞれSQLが実行されます。
こんな感じ

Executing :
 SELECT me.id, me.rid, me.name, me.created_on, me.timestamp
FROM member me
ORDER BY me.id DESC :

 -->Query Time: 0.001609.
 -->ALL Query Time: 0.001609
---------------------------------------------------------------------------------
8 at ./TestDBIC/Script/Test.pm line 11.
7 at ./TestDBIC/Script/Test.pm line 11.
Executing :
 SELECT me.id, me.rid, me.name, me.created_on, me.timestamp
FROM member me
ORDER BY me.id DESC :

 -->Query Time: 0.000998.
 -->ALL Query Time: 0.002607
---------------------------------------------------------------------------------
8 at ./TestDBIC/Script/Test.pm line 15.
7 at ./TestDBIC/Script/Test.pm line 15.

しかし、

my $itr = $self->model('Member')->search({},{cache => 1});
while (my $member = $itr->next) {
    warn $member->id;
}
$itr->reset;
while (my $member = $itr->next) {
    warn $member->id;
}

こんな感じでcacheを設定してやれば
1個目のwhileでSQLが実行され、
2個目のwhileでは1個目の結果が再利用されます。
こんな感じ

Executing :
 SELECT me.id, me.rid, me.name, me.created_on, me.timestamp
FROM member me
ORDER BY me.id DESC :

 -->Query Time: 0.001563.
 -->ALL Query Time: 0.001563
---------------------------------------------------------------------------------
8 at ./TestDBIC/Script/Test.pm line 11.
7 at ./TestDBIC/Script/Test.pm line 11.
8 at ./TestDBIC/Script/Test.pm line 15.
7 at ./TestDBIC/Script/Test.pm line 15.

ただ、インスタンスを捨てるとダメ。当然だけど。

まあ、普通にCache::Memcachedを使ってキャッシュするのであれば、

sub cache {
    my $self = shift;
    $self->{__cache} ||= Cache::Memcached->new({
        servers => [ $self->config->cache_servers ],
    });
}

sub run {
    my $self = shift;

    my $results = $self->cache->get('test_cache');
    unless ( $results ) {
        $results = [ $self->model('Member')->search({},{}) ];
        $self->cache->set('test_cache', $results, 60*10);
    }
    for my $member (@{$results}) {
        warn $member->id;
    }
}

こんな感じになるかな。でも微妙っす。