Rails中的Active Record的关联功能很强大,但是有时会产生N+1 SQL 查询问题。比如查看一篇文章下的很多评论就会产生N+1 问题。
PS: 问题往往出现在一对多和多对多的关系中。
参考资料: ihower实战圣经
解决思路如下:
1. 安装检测工具
(1)gem 'rack-mini-profiler'
,效能检测工具。安装后,网页上左上角会出现网页加载时间的提示。
(2)gem 'bullet', group: 'development'
, N+1 query检测工具。使用流程可参考:bulldet,当你的代码存在N+1问题时,会出现例如下面的提示:1
2
3
4USE eager loading detected
Post => [:user]
Add to your finder: :includes => [:user]
Call stack
2. 使用 inclueds 关联
(1)model 之间的关系1
2
3
4
5
6
7class User < ApplicationRecord
has_many :posts
end
class Post < ApplicationRecord
belongs_to :user
end
(2)修改控制器中代码1
2
3
4
5class PostsController < ApplicationController
def index
posts = Post.includes(:user).page(params[:page])
end
end
此时,就会观察到rails log中只会出现两条SQL查询语句,。1
2Comment Load (0.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 1]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (4, 18, 2, 14, 13, 3, 12)
N + 1 其实属于是慢查询的问题,下面就大体总结下解决慢查询问题及解决方法:
- N + 1 ——– ——–includes
- 大量数据 ———– find_each(或者 find_in_batches)
- 查询慢 ————– 加 索引
- 捞出所需字段 —— select 方法
- 计数快取 ———- Counter cache