Techniques for reducing database queries in a Rails app Techniques for reducing database queries in a Rails app database database

Techniques for reducing database queries in a Rails app


Check out: bullet

Its a great way to identify n+1 queries and it offers suggestions to minimize it.

It does slow down development mode, so be sure to disable it when you are not performance tuning.

While we are at it, also checkout: rails_indexes

A simple way to identify which indexes your app could be missing.

Happy tuning.


One common practice is judicious use of the include => :association option.

For instance on a controller you might do:

def show    @items = Item.find(:all) end

...and the show view would do something like:

<% @items.each |item| %>    <%= item.product.title %><% end %>

This will create a query for every call to product. But if you declare the association included as follows, you get eagerly-loaded associations in one query:

def show    @items = Item.find(:all, :include => :product)end

As always, check your console for query times and such.


I am useing :joins and :select options if you need just to display data.I found very useful named_scope to define all possible :joins and one :select_columns named_scope. Example

    class Activity < ActiveRecord::Base      belongs_to :event      belongs_to :html_template      has_many :participants      named_scope :join_event, :joins => :event      named_scope :join_owner, :joins => {:event => :owner}      named_scope :left_join_html_template,       :joins => "LEFT JOIN html_templates ON html_templates.id = activities.html_template_id"      named_scope :select_columns, lambda { |columns| {:select => columns}}      named_scope :order, lambda{ |order| {:order => order}}end

So now you can easly build queries like this:

columns = "activities.*,events.title,events.owner_id,owners.full_name as owner_name"@activities = Activity.join_event.join_owner.order("date_from ASC").select_columns(columns)

I consider this is not the best and safest way, but in my case it really minify query count that executes per request and there are no errors rised about some wrong generated queries yet.