假設部落格模型:
class Post < ActiveRecord::Base
belongs_to :author
has_many :comments, :order => 'created_on DESC'
end
遍歷所有文章並存取作者與最新評論:
for post in Post.find(:all)
puts "Post: #{post.title}"
puts "Written by: #{post.author.name}"
puts "Last comment on: #{post.comments.first.created_on}"
end
執行 1 次查詢 posts + N 次查詢 authors + N 次查詢 comments = 2N+1 次查詢。N=100 即 201 次資料庫往返,效能嚴重下降。
:include 預加載# 單一關聯預加載
for post in Post.find(:all, :include => :author)
# ... 只需 2 次查詢 (posts + authors)
end
# 多重關聯一次預加載
for post in Post.find(:all, :include => [:author, :comments])
# ... 僅 1 次查詢 (LEFT OUTER JOIN posts, authors, comments)
end
使用 :include 時,:conditions 中的欄位必須加表名前綴消除歧義:
Post.find(:all,
:conditions => "posts.title LIKE '%ruby%'",
:include => [:author, :comments]
)
config.active_record.logger = Logger.new(STDOUT)),觀察查詢數:include:joins 手寫 SQL 精確控制:select 限制欄位,減少記憶體佔用預加載是解決 N+1 問題的利器,但需權衡記憶體與查詢複雜度,實測為準。