日々徒然

プログラミングしたりお酒飲んだりする毎日

Railsのクエリキャッシュについて

Railsのクエリキャッシュについて

仕組み

ActiveRecordはクエリキャッシュという機能がある Partner.find(1)という処理が走った時に 1. ActiveRecordPartner.find(1)SELECT 'partners'.* FROM 'partners' WHERE 'partners'.'id' = 1という SQLクエリに変換してDBに問い合わせる 1. DBから返ってきた情報を元にPartnerクラスのインスタンスを作成する

この処理の中でSQLクエリと実行結果をキャッシュに保存する 再度同じ処理をする時にキャッシュを使ったほうが、DBに再アクセスするよりも高速に行える

irb(main):011:0> user = User.where(id: 1)
D, [2021-08-17T17:59:50.832891 #221] DEBUG -- :   User Load (0.7ms)  SELECT `users`.* FROM `users` WHERE `users`.`deleted_at` IS NULL AND `users`.`id` = 1
# この時にキャッシュされる

irb(main):012:0> user.first.email
=> "example@example.com"

# user id:1のemailを書き換え
user.find(1).update!(email: "changed@example.com")

# userを確認
irb(main):015:0> user
=> [#<User id: 1, email: "example@example.com", created_at: "2021-08-17 10:42:23.000000000 +0900", updated_at: "2021-08-17 17:59:36.000000000 +0900", deleted_at: nil>]
# 最初のSQLのキャッシュが残っているため、DBの値が更新されていても値が変わっていない

# reloadすると再度クエリが走るため値が変わる
irb(main):016:0> user.reload
D, [2021-08-17T18:03:12.599594 #221] DEBUG -- :   User Load (0.7ms)  SELECT `users`.* FROM `users` WHERE `users`.`deleted_at` IS NULL AND `users`.`id` = 1
=> [#<User id: 1, email: "changed@example.com", created_at: "2021-08-17 10:42:23.000000000 +0900", updated_at: "2021-08-17 18:01:06.000000000 +0900", deleted_at: nil>]

注意

  • クエリキャッシュが残るのは1リクエスト中のみ
  • キャッシュされた値はそのリクエスト中はDBが書き換わってもそのままなので気を付ける

参考にしたサイト

Rails のクエリキャッシュの仕組みを調べた - takatoshiono's blog はじめに 〜SQLキャッシュにまつわる失敗〜|Ruby on Rails のSQLキャッシュ(書きかけ)