The Importance of Being Eagerly Loaded
I'm working in refactoring a Rails application for a client. Besides doing a lot of refactoring in the views, I started to look at the logs and discovered that the database is being bombarded repeatedly with very similar queries every time you request a page.
I wanted to find out why this happened, and after reading about tuning the performance tuning of Rails applications, I found some material about N+1 queries. Aha. Apparently those fancy methods of accessing associations can bite you in the ass if you don't use them correctly.
N+1 queries mean that if you ask for all the records of a specific model, and their associated models, Rails is going to query the database as many times as the associated models exists per each parent. So if you roughly had 10 records and 5 associations for each of them, Rails would query the database about 50 times.
In this application we have a big joint structure, and relationships upon the objects are called in almost every view.
Fortunately, Rails being Rails, has a fancy way to reducing the amout of queries done to the database by usign the SQL 'IN' clause, that is called 'includes'.
Checkout the before & after adding 'include' in this query:
#Associations without eager loading Page.all.each do |page| #... page.object_maps.each do |object_map| #... object_map.object_properties.each do |object_property| #... end end end
After implementing include:
#Associations with eager loading cause the second log Page.includes(object_maps: :object_properties).all.each do |page| #... page.object_maps.each do |object_map| #... object_map.object_properties.each do |object_property| #... end end end
The results are 37 queries to the database vs 3 queries. The difference increases even more when your amount of records grow. Be sure to consider using eager loading if you are suffering performance issues.