真实世界中的Rails,第3部分: 优化ActiveRecord - 编程入门网
ls,第3部分: 优化ActiveRecord(4)
时间:2011-11-20
由于您应该看 到针对每个地址的查询,所以就性能而言,结果并不尽如人意。清单 6 给出了问题的全部: 清单 6. N+1 问题的查询 ^[[4;36;1mMember Load (0.004063)^[[0m ^[[0;1mSELECT * FROM members WHERE (members.`id` IN (1,2,3)) ^[[0m ^[[36;2m./vendor/plugins/paginating_find/lib/paginating_find.rb:98:in `find''^[[0m ^[[4;35;1mAddress Load (0.000989)^[[0m ^[[0mSELECT * FROM addresses WHERE (addresses.addressable_id = 1 AND addresses.addressable_type = ''Member'') LIMIT 1^ [[0m ^[[35;2m./vendor/plugins/paginating_find/lib/paginating_find.rb:98:in `find''^[[0m ^[[4;36;1mAddress Columns (0.073840)^[[0m ^[[0;1mSHOW FIELDS FROM addresses^[[0m ^[[4;35;1mAddress Load (0.002012)^[[0m ^[[0mSELECT * FROM addresses WHERE (addresses.addressable_id = 2 AND addresses.addressable_type = ''Member'') LIMIT 1^ [[0m ^[[35;2m./vendor/plugins/paginating_find/lib/paginating_find.rb:98:in `find''^[[0m ^[[4;36;1mAddress Load (0.000792)^[[0m ^[[0;1mSELECT * FROM addresses WHERE (addresses.addressable_id = 3 AND addresses.addressable_type = ''Member'') LIMIT 1^ [[0m ^[[36;2m./vendor/plugins/paginating_find/lib/paginating_find.rb:98:in `find''^ [[0m 结果正如我所预见的那样糟糕。所有成员共用一个查询,而每个地址各用一个查询。我们 检索了三个成员,所以一共用了四个查询。如果是 N 个成员,就会有 N+1 个查询。这就是可怕的 N+1 问题。大多数持久性框架都采用热关联(eager association)来解决该问题。Rails 也不例外。如果需 要访问关系,就可以选择将其包括到初始查询中。ActiveRecord 使用 :include 选项来实现此目的。如 果将查询更改为 Member.find([1,2,3], :include => :address).each {|member| puts member.address.city},结果就会稍好一些: 清单 7. 解决 N+1 问题 ^ [[4;35;1mMember Load Including Associations (0.004458)^[[0m ^[ [0mSELECT members.`id` AS t0_r0, members.`type` AS t0_r1, members.`about_me` AS t0_r2, members.`about_philanthropy` ... addresses.`id` AS t1_r0, addresses.`address1` AS t1_r1, addresses.`address2` AS t1_r2, addresses.`city` AS t1_r3, ... addresses.`addressable_id` AS t1_r8 FROM members LEFT OUTER JOIN addresses ON addresses.addressable_id = members.id AND addresses.addressable_type = ''Member'' WHERE (members.`id` IN (1,2,3)) ^[ [0m ^[[35;2m./vendor/plugins/paginating_find/lib/paginating_find.rb: 98:in `find''^[[0m 真实世界中的Rails,第3部分: 优化ActiveRecord(5)时间:2011-11-20该查询的速度也会更快。一个查询会检索所有成员和地址。这就是热关联的工作原理。 通过 ActiveRecord,还可以嵌套 :include 选项,但嵌套深度只有一级。例如,有多个 contacts 的 Member 以及有一个 address 的 Contact 就属于这种情况。如果想要为某个成员的联系人显示所有城市,就可以 使用清单 8 中所示的代码: 清单 8: 为某个成员的联系人获取城市 member = Member.find(1) member.contacts.each {|contact| puts contact.address.city} 该代码应该能够工作,但必 须要针对此成员、每个联系人以及每个联系人的地址进行查询。通过用 :include => :contacts 包括 :contacts,可以稍许提高性能。也可以通过将二者都 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |