2
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 3 years have passed since last update.

[Rails]bulletを使ってN + 1問題を解消

Last updated at Posted at 2021-04-30

##N + 1問題とは
要約するとSQLが沢山発行して動作が重くなってしまう問題
詳しくは以下の記事をご確認ください私も参考にさせていただきました。

bulletとは

N + 1クエリを自動で検出するgemですうっかりN+1問題が起こってもすぐに見つけることができます。
ただbulletが検出できないようなN + 1クエリがあるケースがあるので頼りすぎるのもよくないです。↓以下参考記事

bulletを使う前

自作のアプリケーションでSQLを発行し確認してみたところ以下のようになった

Processing by QuestionsController#index as HTML
  User Load (0.7ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 18], ["LIMIT", 1]]
  Rendering questions/index.html.erb within layouts/application
  Question Load (1.3ms)  SELECT DISTINCT "questions".* FROM "questions" WHERE "questions"."best_answer_id" IS NULL ORDER BY "questions"."created_at" DESC LIMIT $1 OFFSET $2  [["LIMIT", 10], ["OFFSET", 0]]
  ↳ app/views/questions/index.html.erb:51
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 18], ["LIMIT", 1]]
  ↳ app/views/questions/index.html.erb:52

これが100行ぐらい続くのである。。

##bulletをインストール
Gemfileに以下を追加します。

Gemfile
group :development
  gem 'bullet'
end

bundle installを実行します。

$ bundle install

そしてSQLを発行しているページにいく(筆者の場合indexページ)と以下のように表示された。
スクリーンショット 2021-05-01 1.21.46.png

表示の通りコントローラーにincludes[:user])に書き換える

- @questions = @q.result(distinct: true)
+ @questions = @q.result.includes(:user)

こうするとポップアップが表示されなくなりSQLがどう発行されているか確認してみた。

Processing by QuestionsController#index as HTML
  User Load (1.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 18], ["LIMIT", 1]]
  Rendering questions/index.html.erb within layouts/application
  Question Load (0.7ms)  SELECT "questions".* FROM "questions" WHERE "questions"."best_answer_id" IS NULL ORDER BY "questions"."created_at" DESC LIMIT $1 OFFSET $2  [["LIMIT", 10], ["OFFSET", 0]]
  ↳ app/views/questions/index.html.erb:51
  User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2, $3, $4, $5, $6, $7, $8)  [["id", 18], ["id", 17], ["id", 14], ["id", 19], ["id", 13], ["id", 9], ["id", 11], ["id", 3]]
  ↳ app/views/questions/index.html.erb:51

70行ぐらいに減っていた!

includesを指定することで関連をまとめて取得し、最小限のクエリ回数で読み込みます。

以上です

2
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
2
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?