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に移し替えてから格納するのがよさそうですね。