Cha*_*son 13 activerecord ruby-on-rails
如果我这样做
post = Post.find_by_id(post_id, :include => :comments)
Run Code Online (Sandbox Code Playgroud)
执行两个查询(一个用于发布数据,另一个用于帖子的评论).然后,当我发布post.com时,不执行另一个查询,因为数据已经被缓存.
有没有办法只做一个查询,仍然通过post.comments访问评论?
Mat*_*chu 34
不,那里没有.这是预期的行为:include,因为这种JOIN方法最终效率低下.
例如,请考虑以下情形:Post模型有3个字段需要选择,2个字段用于Comment此特定帖子有100个注释.Rails 可以运行单个JOIN查询:
SELECT post.id, post.title, post.author_id, comment.id, comment.body
FROM posts
INNER JOIN comments ON comment.post_id = post.id
WHERE post.id = 1
Run Code Online (Sandbox Code Playgroud)
这将返回以下结果表:
post.id | post.title | post.author_id | comment.id | comment.body
---------+------------+----------------+------------+--------------
1 | Hello! | 1 | 1 | First!
1 | Hello! | 1 | 2 | Second!
1 | Hello! | 1 | 3 | Third!
1 | Hello! | 1 | 4 | Fourth!
...96 more...
Run Code Online (Sandbox Code Playgroud)
你已经可以看到问题了.单查询JOIN方法虽然返回了您需要的数据,但会以冗余方式返回.当数据库服务器将结果集发送给Rails时,它将分别发送帖子的ID,标题和作者ID 100次.现在,假设Post您有10个感兴趣的字段,其中8个是文本块.好恶.这是很多数据.将数据从数据库传输到Rails 确实需要在CPU周期和RAM中进行双方工作,因此最大限度地减少数据传输对于使应用程序运行更快更精简非常重要.
Rails开发人员对这些数字进行了碾压,大多数应用程序在使用多次查询时运行得更好,这些查询只获取一次数据,而不是一次查询可能会造成巨大冗余.
当然,也有来自于每个开发者的生命的时候,一个连接是为了运行复杂的必要条件,而且可以通过更换可实现:include与:joins.但是,对于预取关系,Rails接受的方法:include对性能要好得多.
如果您使用这种急切加载的关联行为,您将获得单个(高效)查询.
这是一个例子:
假设您有以下型号(:user外部参考在哪里):
class Item < ActiveRecord::Base
attr_accessible :name, :user_id
belongs_to :user
end
Run Code Online (Sandbox Code Playgroud)然后执行它(注意:该where部分是至关重要的,因为它欺骗Rails来生成单个查询):
@items = Item.includes(:user).where("users.id IS NOT NULL").all
Run Code Online (Sandbox Code Playgroud)
将导致单个SQL查询(下面的语法是PostgreSQL的语法):
SELECT "items"."id" AS t0_r0, "items"."user_id" AS t0_r1,
"items"."name" AS t0_r2, "items"."created_at" AS t0_r3,
"items"."updated_at" AS t0_r4, "users"."id" AS t1_r0,
"users"."email" AS t1_r1, "users"."created_at" AS t1_r4,
"users"."updated_at" AS t1_r5
FROM "measurements"
LEFT OUTER JOIN "users" ON "users"."id" = "items"."user_id"
WHERE (users.id IS NOT NULL)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9978 次 |
| 最近记录: |