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.