riddhi_agrawal
riddhi_agrawal

Reputation: 215

why is Active Record firing extra query when I use Includes method to fetch data

I have the following model structure:

class Group < ActiveRecord::Base
  has_many    :group_products, :dependent => :destroy
  has_many    :products, :through => :group_products
end

class Product < ActiveRecord::Base
  has_many  :group_products, :dependent => :destroy
  has_many  :groups, :through => :group_products
end

class GroupProduct < ActiveRecord::Base
  belongs_to :group
  belongs_to :product
end

I wanted to minimize my database queries so I decided to use includes.In the console I tried something like,

groups = Group.includes(:products)

my development logs show the following calls,

Group Load (403.0ms)  SELECT `groups`.* FROM `groups`
GroupProduct Load (60.0ms)  SELECT `group_products`.* FROM `group_products` WHERE (`group_products`.group_id IN (1,3,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,33,42,49,51))
Product Load (22.0ms)  SELECT `products`.* FROM `products` WHERE (`products`.`id` IN (382,304,353,12,63,103,104,105,262,377,263,264,265,283,284,285,286,287,302,306,307,308,328,335,336,337,340,355,59,60,61,247,309,311,66,30,274,294,324,350,140,176,177,178,64,240,327,332,338,380,383,252,254,255,256,257,325,326))
Product Load (10.0ms)  SELECT `products`.* FROM `products` WHERE (`products`.`id` = 377) LIMIT 1

I could analyze the initial three calls were necessary but don't get the reason why the last database call is made,

 Product Load (10.0ms)  SELECT `products`.* FROM `products` WHERE (`products`.`id` = 377) LIMIT 1

Any idea why this is happening? Thanks in advance. :)

Upvotes: 3

Views: 1413

Answers (3)

Rameshwar Vyevhare
Rameshwar Vyevhare

Reputation: 2759

Now you can easily find N+1 query call using bullet gem (help to kill N+1 queries and unused eager loading.)

Use this gem it will tell you where you need to work around to kill N+1 call and also tell if somewhere eager loading not requires.

It helps me lot use this and then try it out, you will get solution of your problem.

Read below article explain you more about different ways to perform eager loading -

3 ways to do eager loading (preloading) in Rails 3 & 4

Upvotes: -1

Sunil Sandhu
Sunil Sandhu

Reputation: 21

I was having a similar issue when issuing a where() call. The problem was due to some "lazy evaluation" being done for ActiveRecords::Relation (as sailor mentioned above). The solution is to simply add a .to_a at the end of the call. It should work for your includes() statement above too. For more info, see:

http://daveinabottle.schweisguth.org/2011/05/01/avoiding-extra-queries-in-activerecord-3/

Upvotes: 2

tsherif
tsherif

Reputation: 11710

I don't think that fourth query is coming from this line of code (or the collection created by it). Even if you did something like groups.products.find(product_id) somewhere later, you would see a much more complex query, with the inner joins on the join table. It looks like there must be a separate Product.find(product_id) or something similar somewhere in your code.

Upvotes: 0

Related Questions