1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Rails][Ruby] update_allとwhereを使用するときに気をつけること

Last updated at Posted at 2022-06-18

はじめに

未経験からエンジニアに転職して、2ヶ月ほど経つエンジニアです。
業務にあたりながらも、小規模なアプリを作って楽しんでいます。
今回は大量のレコードをまとめて更新するときに重宝する update_all についてです。

結論

update_all を使用するときはクエリの実行タイミングに注意しよう。

update_all とは

条件に一致するレコードをSQLを直接実行して全て更新
updated_atとupdated_onは更新されない

バリデーションやトランザクションを無視する点も注意が必要です。

クエリキャッシュのタイミングに注意

def update_user_data
 #このタイミングではクエリは走らない
 users = User.where(id: XXX, status: XXX, ...) 

 #上記 where と組み合わせて UPDATE users ... FROM ... WHERE ... が走る
 users.update_all(
   status: XXX,
   updated_at: Time.current
  ) 

 # この時、usersは空になってしまう (SELECT * FROM users WHERE ... が走る)
 # p users = []
 users.each do |i|
  ...
 end
end

そもそもupdate_allが必要なのか検討してみてください。
update_allを使用したい場合は以下のようにすることで解決できます。

def update_user_data
 #このタイミングではクエリは走らない
 users = User.where(id: XXX, status: XXX, ...) 
 # users を保存しておく(ActiveRecord:Relationではない状態にして保存)
 users_before_update_all = users.to_a

 #上記 where と組み合わせて UPDATE users ... FROM ... WHERE ... が走る
 users.update_all(
   status: XXX,
   updated_at: Time.current
  ) 

 # 保存した方を使う
 users_before_update_all.each do |i|
  ...
 end
end

まとめ

update_allは
複数のレコードを一括で更新できます。
DBへの負荷を軽減できます。

一方で、下記のような注意するべき点があります。

  • バリデーションを実行しない
  • トランザクションを実行しない
  • 更新前の状態に依存する
  • updated_at を自動更新しない

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?