DBを操作するメソッドはクエリを実行する
DBを操作するメソッドを呼び出すとクエリが実行される。
よく使われるのは以下のメソッドだろう。
参照系
・find
・find_by
・where
作成・更新系
・create
・update
・save
削除
・destroy
上記のwhere, update, saveを除いては、呼び出しの度に必ず1回クエリが実行される。
updateはインスタンスに変更がある場合のみクエリを実行する。
saveは新規レコードの場合、又は既存レコードで変更がある場合にクエリを実行する。(正確には update, saveはトランザクションのBEGIN, COMMITクエリを無条件に実行しているが、このクエリは便宜上無視している)
whereの挙動
whereは初回は必ずクエリを実行するが、前回と同じ条件の場合、2回目以降は1回目の結果のキャッシュを返すのでクエリは実行されない。
尚、ここでキャッシュされると言っているのはwhereが返すActiveRecord_Relationインスタンスに対して、前回と同じ条件で呼び出した場合のこと。
pry(main)> activerecord_relation = User.where(id:1);
# 初回はクエリを実行する
pry(main)> activerecord_relation.to_a;
User Load (0.3ms) [Shard: master] SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
# 同じ条件の場合、2回目以降はクエリを実行しない
pry(main)> activerecord_relation.to_a;
# 以下は毎回別のActiveRecord_Relationインスタンスが生成されるので毎回クエリが実行される
pry(main)> User.where(id:1).to_a;
User Load (0.3ms) [Shard: master] SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
pry(main)> User.where(id:1).to_a;
User Load (0.3ms) [Shard: master] SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
上記の他に使用頻度が高いのはbelogs_to, has_manyなどで定義されたアソシエーションを呼び出す場合。
アソシエーションは基本的*にwhereと同じように初回はクエリを実行し、同じ条件で呼び出した場合は2回目以降はキャッシュを返す。
* 通常、アソシエーションはカラムの値で関連レコードを検索するが、belogs_toなどのアソシエーションの定義の際にLambdaを渡すことで動的に検索条件を変化させることがでる。
まとめ
基本的にはDB操作をするメソッド呼び出したら、初回の1回はクエリが実行されているのだな、と認識する。
その上で、実装したコードを実行し、ログ(development.logなど)に流れるクエリの回数が概ね意図通りか確認する。
この時、同じテーブルに対し複数回似たようなクエリが流れている場合は、それを省略し、パフォーマンスを改善する余地があるかもしれない。
コメント