Eager loading.

SO, What’s the problem?

In active record query interface there is a lot of room to get in your own way and slow down the response time.  The #each method is a prime place to fall into this mistake.  Lets say you have thousands of Accounts – and lets say that the Account model is an STI.  Some of the accounts are type ‘client’ and some are type ’employee’.  What if we wanted to find all of the employees that have ‘billed_time’.  This doesn’t mean that every single employee in the Accounts table will have ‘billed_time.’

So, let’s say that we want to find all of the employees with billed time.  In the active record query interface we might run something like this

Employee.all.each { |employee| puts employee.billed_time.count }

Seems pretty simple, yeah.  Well, let’s take a look at it.

This query is actually running several queries.  First, the Employee.all.each means that EVERY single employee will be check to see if they do in fact have any billed time.  If you have a rather large data set, this can get expensive.  So, it goes through each employee, finds the ones that have billed_time and adds to the count.  Is there a more effective way of doing this?

So, what’s eager loading?

Eager loading is the mechanism for loading the associated records of the objects returned by Model.find using as few queries as possible.

Whenever you ‘pre-load’ a list of items, then you will not have to go through each row of the database looking for records that match your query.

Let’s look at it like this.  Let’s say that you want to take the same query as the above – you want to find all the employees from the Account model and see how many billed_time entries it has.  We can preload only employees who fit the first criteria, then use the .each method to iterate over the list we have preloaded.  Let’s try.  First we use the #includes method to preload the data.

employees = Employees.includes(:billed_time).first(5)

So, what we have done here is preloaded employees that have billed ours and only took the first 5 and assigned that to a variable of ’employees’.  We have ‘pre-loaded’ data that we will need – now we can use #each to iterate over each employee and do whatever we want.  Let’s say we just wanted to #count the number of billed_time entries each employee has.  Well –

employees.each { |employee| puts employee.billed_time.count }

So, we have the same result and had to ask the database far less questions.  That is the idea behind eager loading.  Now, this example was a little weird, having the STI with Accounts, but still.  Eager loading is a way to optimize your queries, lessen time, and ask less questions in retrieving data.  I’ll give a link to a good little resource.  Happy coding.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s