rails: N+1 查询问题以及优化

N+1 查询问题,以及优化方案
更新于: 2025-11-07 08:18:10

问题

N+1 查询问题是指在获取关联数据时,产生大量额外数据库查询的性能问题。

# 获取所有文章
posts = Post.all

# 遍历文章并访问关联的用户信息
posts.each do |post|
  puts post.user.name  # 每次都会查询数据库!
end

ps: 测试数据

posts = Post.limit(10)  # 只取10篇,避免输出太多
posts.each { |post| puts post.user.name }

查询次数分析

执行的查询:
1 次查询获取所有文章:SELECT * FROM posts
N 次查询获取每个文章的用户:SELECT * FROM users WHERE id = ? (N = 文章数量)
如果数据库中有 100 篇文章,就会执行 1 + 100 = 101 次查询!

使用预加载(eager loading)

# 预加载关联数据
posts = Post.includes(:user)

posts.each do |post|
  puts post.user.name  # 不会再次查询数据库
end

查询分析

1 次查询获取文章:SELECT * FROM posts
1 次查询获取所有相关用户:SELECT * FROM users WHERE id IN [1,2,3,4,5...]
总共只执行 2 次查询,而不是 1+N 次!

ps: 测试数据

posts = Post.includes(:user).limit(10)
posts.each { |post| puts post.user.name }