読者です 読者をやめる 読者になる 読者になる

ログってなんぼ

日々のメモです

ああ、N+1問題ってそれのことね

プログラマの人達の会話でN+1問題という単語をよく聞いていて

N-1問題 - Wikipedia

のはなしでも無さそうだし

何の話かわからず聞き流してたんですが

article.rb

class Article < ApplicationRecord
    belongs_to :user
end

user.rb

class User < ApplicationRecord
    has_many :articles
end

articles_controller.rb

  def index
    @articles = Article.all
  end

SQL

Started GET "/articles" for 127.0.0.1 at 2016-12-20 20:34:08 +0900
Processing by ArticlesController#index as HTML
  Rendering articles/index.html.erb within layouts/application

  Article Load (0.4ms)  SELECT `articles`.* FROM `articles`
  User Load (25.6ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 4 LIMIT 1
  User Load (0.2ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 5 LIMIT 1
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 6 LIMIT 1
  User Load (0.5ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 7 LIMIT 1
  User Load (0.7ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 8 LIMIT 1
  User Load (0.4ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 9 LIMIT 1
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 10 LIMIT 1
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 11 LIMIT 1
  User Load (0.2ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 12 LIMIT 1
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 13 LIMIT 1
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 14 LIMIT 1
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 15 LIMIT 1
  User Load (0.2ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 16 LIMIT 1
  User Load (0.2ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 17 LIMIT 1
  User Load (0.2ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 18 LIMIT 1
  User Load (0.2ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 19 LIMIT 1
  User Load (0.2ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 20 LIMIT 1

  Rendered articles/index.html.erb within layouts/application (104.0ms)
Completed 200 OK in 1085ms (Views: 1043.0ms | ActiveRecord: 33.8ms)

ああ、コレのことね。これにそういう名前がついてんのね・・・

普通にWHERE IN使おうね

articles_controller.rb

  def index
    @articles = Article.all.includes(:user)
  end

SQL

Started GET "/articles" for 127.0.0.1 at 2016-12-20 20:38:04 +0900
Processing by ArticlesController#index as HTML
  Rendering articles/index.html.erb within layouts/application

  Article Load (0.8ms)  SELECT `articles`.* FROM `articles`
  User Load (30.6ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)

  Rendered articles/index.html.erb within layouts/application (62.7ms)
Completed 200 OK in 119ms (Views: 78.3ms | ActiveRecord: 34.0ms)

○○問題、ってついてるからなんか不可避のパラドックスみたいなことかと思ってたんですが単にORマッパーの挙動の話なんですね。

書いてるコードがどういうSQL流してるのか意識しておきたいもんですね。

とりあえず共有しときますね

github.com

つかコーディング中ってログ見ないの?(´・ω・`)

N+1クエリの発見用ツール

これ良いらしいです

github.com