Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Rails ActiveRecordのアンチパターン 初心者→中級者へのSTEP22/25

Rails ActiveRecordのアンチパターン

はじめに

急にスケジュールが詰め詰めになったので、残り4日とわずかですが、今回は少なめです。すみません...
頑張ります。
今回はActiveRecordにおけるアンチパターンについて。パフォーマンスを落とすようなコードを書かないようにアンチパターンを日々、覚えるようにしましょう。

All Each Pattern

User.allなどでレコードを全取得してそこからeachで回すパターン。

User.all.each do|user|
  if user.created_at >= Date.new(2018)
    user.point += 100
    user.save
  end
end

2018年以降に登録してくれたユーザにポイントをプレゼントしよう的なコード(ほぼ参考元のコードです。すみません)

ダメなとこ
1,Userの全件取得でメモリを圧迫。
2,eachメソッドにより取得したユーザー全件を一気にメモリに展開してから処理するので、こちらもよろしくない。

改善策
1,そもそも全件取得する必要がない。whereを使って取得件数を下げる。
2,find_eachメソッドを使って、分割して処理する。(find_eachメソッドはeachメソッドと違って、一気にではなく分割して処理する。)

改善後

User.where("created_at >= ?", Date.new(2018)).find_each do |user|
    user.point += 100
    user.save
end

よくなりました...と思いきや、まだ問題があります。

N+1 update queries pattern

前にN+1問題は書きましたね。↓
RailsのN+1問題の解決方法 初心者→中級者へのSTEP9/25

似たような感じの問題です。1回のselectに対し、N回のupdateが起きています。1回にしましょう。
update_allを使う。

再改善後

User.where("created_at >= ?", Date.new(2018)).update_all("point = point + 100")

以前書きましたが、update_allはバリデーションをしませんので今回は問題ないですが、パフォーマンスが上がる!と言っってむやみに使ってはダメです。

これでパフォーマンスがぐぐっと上がるはずです。

まとめ

なんかほぼ自分のブログみたいになってきたこのカレンダー。お家がゴタゴタして書く暇あるか微妙ですが、残り数日休まず記事をあげたいです。今回のアンチパターンは参考元のスライドが非常にわかりやすいです。興味持ったらぜひそちらを読んでください。他の例も載せてくださってます。

参考にしたの

ActiveRecordデータ処理アンチパターン
https://speakerdeck.com/toshimaru/active-record-anti-patterns?slide=26

簡単に始められるRailsパフォーマンス改善
https://qiita.com/yu-croco/items/d7a39b34036d638c5026

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
6
Help us understand the problem. What are the problem?