2014年9月30日火曜日

ActiveRecordをRails.cacheに入れてみたときの挙動

ActiveRecordでDBから取得した内容をキャッシュしたかったのでRails.cacheに入れてみました。

開発環境ではcacheが効かないようになっているので有効にする。
config/environments/development.rb
 config.action_controller.perform_caching = true

例としてサービスマスタのModelを作成
mst_service.rb
class MstService < ActiveRecord::Base
end

controllerから以下のようなコードでcacheを利用
    puts "cache_#{Rails.cache.read("mst_service").nil?}"
    mst_service = Rails.cache.fetch("mst_service",expires_in: 1.minutes) do
      mst = MstService.select(:service_id).where(:status => '0')
      mst
    end

4回アクセスした時の標準出力は以下のようになる。
2回目以降はキャッシュから取得できているようです。
cache_true
cache_false
cache_false
cache_false

DBへのアクセスはこんな感じ。
アクセス回数分、DBにselectが投げられている。。。
MstService Load (0.3ms)  SELECT `mst_services`.`service_id` FROM `mst_services`  WHERE `mst_services`.`status` = '0'
MstService Load (0.4ms)  SELECT `mst_services`.`service_id` FROM `mst_services`  WHERE `mst_services`.`status` = '0'
MstService Load (0.2ms)  SELECT `mst_services`.`service_id` FROM `mst_services`  WHERE `mst_services`.`status` = '0'
MstService Load (0.2ms)  SELECT `mst_services`.`service_id` FROM `mst_services`  WHERE `mst_services`.`status` = '0'

cacheには入っているようですが、DBへのアクセスが減っておらず、
やりたいことはDBへのアクセスを減らすことなので、意図したキャッシュの処理にはなっていません。
毎回SQLが発行されていることから、ActiveRecordの状態がキャッシュされていて、
データがキャッシュされる訳ではなさそうです。

DBから取得した内容をhashに入れてからキャッシュするように変えてみました。
    puts "cache_#{Rails.cache.read("mst_service").nil?}"
    mst_service = Rails.cache.fetch("mst_service",expires_in: 1.minutes) do
      mst_data = MstService.select(:service_id).where(:status => '0')
      mst = {}
      mst_data.each do |data|
        mst.store(data.service_id,data.service_id)
      end
      mst
    end

4回アクセスした時の標準出力は以下のようになりました。
上のと内容は同じです。
cache_true
cache_false
cache_false
cache_false

DBへのアクセスを確認したところ、以下のように1回だけに減っていました。
MstService Load (0.2ms)  SELECT `mst_services`.`service_id` FROM `mst_services`  WHERE `mst_services`.`status` = '0'

DBから取得した値をRails.cacheに入れるのであれば、ActiveRecordをそのまま入れるのではなく
hashに移し替えてから格納するのがよさそうですね。

0 件のコメント:

コメントを投稿