RailsでのDBへのクエリの組み立ては常にN+1問題との戦いですよね。N+1が発生すると大幅にパフォーマンスがダウンしてしまうので、適切な事前ロードをいかに行えるかがプログラマの腕の見せどころになります。
でもそれって本質でしょうか? DBにクエリを投げる部分の実装の詳細なのでは?
クエリが空気読めばいいじゃん!という「Goldiloader」
「それって実装の本質じゃないよね。詳細だよね。それはクエリを投げる部分(ActiveRecord)が空気読めばいいんじゃね?」
そんな思想で現れたGemがGoldiloaderです。Gemfileに加えるだけで勝手にEager Loadingしてくれるようになります。
このGemをbundleせずに以下のコードを叩くと、eachでposts
が呼ばれるたびにロードを繰り返してしまうのですが・・・
> blogs = Blogs.limit(5).to_a # SELECT * FROM blogs LIMIT 5 > blogs.each { |blog| blog.posts.to_a } # SELECT * FROM posts WHERE blog_id = 1 # SELECT * FROM posts WHERE blog_id = 2 # SELECT * FROM posts WHERE blog_id = 3 # SELECT * FROM posts WHERE blog_id = 4 # SELECT * FROM posts WHERE blog_id = 5
このGemをbundleした後なら、空気を読んで事前にロードしておくてくれます。
> blogs = Blogs.limit(5).to_a # SELECT * FROM blogs LIMIT 5 > blogs.each { |blog| blog.posts.to_a } # SELECT * FROM posts WHERE blog_id IN (1,2,3,4,5)
詳しい話はGem作成元のAUTOMATIC EAGER LOADING IN RAILSという記事をご覧ください。ここのエンジニアブログのRuby on Railsタグの記事、結構面白いです。