SQLの発行件数が多いと指摘を受ける。
業務にて、ある一覧画面を作成していたところ、
自分が書いたソースをみた先輩から、
「この一覧画面のSQLの発行件数が多すぎる。ちょっと減らしてみて。」とご指摘を受けました。
SQLの発行件数が多いのはN+1問題が起きていたことが原因で、
includesを使用することで
事象を解決できたのでアウトプットしてみようと思います。
N+1問題とは
必要以上にSQLが実行されて、パフォーマンスが低下する問題。
今回指摘を受けた画面では、
ログを見ると、他のテーブルの情報を取得するため何度もSQLが発行されていました。
includesとは
includesメソッドは、関連している複数のテーブルからデータをあらかじめ取得するメソッドです。
N+1問題を解決させるためには、
都度SQLを発行させるのではなく、あらかじめデータをすべて取得しておくことで解決することができます。
例えば、
UserクラスとPostクラスがあって、
投稿からユーザ名を取得する処理があったとします。
# models/user.rb
class User < ApplicationRecord
has_many :posts
end
# models/post.rb
class Post < ApplicationRecord
belongs_to :user
end
# 投稿の一覧を取得する
posts = Post.all
posts.each do |post|
p post.user.name
end
上記のメソッドを実行すると、
投稿の数だけSQL文が発行されてしまい、
効率が悪いです。
そこで、下記のようにincludesメソッドを使用して、
あらかじめ投稿に関するユーザ情報を最初にすべて取得します。
そうすることで、
投稿がいくらあってもSQLの発行を一度で済ますことが可能です。
# 投稿と、投稿に関連したユーザ情報を取得する。
posts = Post.includes(:user)
posts.each do |post|
p post.user.name
end
余談
※SQLの発行件数は画面に対してAlt+Pを押下したり、
ログを見ることで確認できます。
参考記事:
https://techacademy.jp/magazine/22031
https://qiita.com/south37/items/b2c81932756d2cd84d7d