n+1查询 http://guides.rubyonrails.org/active_record_querying.html
时间:2010-07-14 来源:cxl2086
N + 1 queries problem
Consider the following code, which finds 10 clients and prints their postcodes:
clients = Client.all(:limit => 10) clients.each do |client| puts client.address.postcode endThis code looks fine at the first sight. But the problem lies within the total number of queries executed. The above code executes 1 ( to find 10 clients ) + 10 ( one per each client to load the address ) = 11 queries in total.
Solution to N + 1 queries problem
Active Record lets you specify all the associations in advanced that are going to be loaded. This is possible by specifying the :include option of the Model.find call. By :include, Active Record ensures that all the specified associations are loaded using minimum possible number of queries.
Revisiting the above case, we could rewrite Client.all to use eager load addresses:
clients = Client.all(:include => :address, :limit => 10) clients.each do |client| puts client.address.postcode endThe above code will execute just 2 queries, as opposed to 11 queries in the previous case:
SELECT * FROM clients SELECT addresses.* FROM addresses WHERE (addresses.client_id IN (1,2,3,4,5,6,7,8,9,10)) Eager Loading Multiple AssociationsActive Record lets you eager load any possible number of associations with a single Model.find call by using an array, hash, or a nested hash of array/hash with the :include option.
5.1.1 Array of Multiple Associations
Post.all :include => [:category, :comments]This loads all the posts and the associated category and comments for each post.
5.1.2 Nested Associations Hash
Category.find 1, :include => {:posts => [{:comments => :guest}, :tags]}The above code finds the category with id 1 and eager loads all the posts associated with the found category. Additionally, it will also eager load every posts’ tags and comments. Every comment’s guest association will get eager loaded as well.