0
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.

N + 1問題を解決する

Posted at

はじめに仕込んでいたgem bulletが警告ログを発したので解決してみます。
スクリーンショット 2021-03-25 19.32.01.png

##N + 1問題とは?
データベースへのアクセス回数が必要以上に多くなってしまう現象の事。モデル間のアソシエーションで発生します。

##gem bulletとは?

N + 1問題が発生してる箇所を警告で教えてくれるgemです。

##現状

CareRecipitent Load (0.4ms)  SELECT "care_recipitents".* FROM "care_recipitents"
  ↳ app/views/caregiver/tops/index.html.erb:1
  Caregiver Load (0.5ms)  SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/views/caregiver/tops/index.html.erb:37
  CACHE Caregiver Load (0.0ms)  SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/views/caregiver/tops/index.html.erb:37
  CACHE Caregiver Load (0.0ms)  SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/views/caregiver/tops/index.html.erb:37
  Rendered caregiver/tops/index.html.erb within layouts/caregiver (Duration: 16.2ms | Allocations: 6553)
  CACHE Caregiver Load (0.1ms)  SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]

はじめに親モデルに検索がかけられ、その後に子モデルに4回クエリが発行されていることがわかります。

##解決策

子モデル.includes(:親モデル)

  def index
    #@caregiver = Caregiver.find(params[:staff_member_id])
  -  @care_recipitents = CareRecipitent.all
  +  @care_recipitents = CareRecipitent.includes(:caregiver)
  end

コントローラーのindexアクションを書き換えます。

CareRecipitent Load (1.2ms)  SELECT "care_recipitents".* FROM "care_recipitents"
  ↳ app/views/caregiver/tops/index.html.erb:1
  Caregiver Load (0.6ms)  SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1  [["id", 1]]
  ↳ app/views/caregiver/tops/index.html.erb:1
  Rendered caregiver/tops/index.html.erb within layouts/caregiver (Duration: 75.3ms | Allocations: 19989)
  Caregiver Load (0.3ms)  SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]

クエリの回数が減り、無事ログを消えました。

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