ActiveRecord使用很方便,只需要声明映射关系,就可以方便地获取各个关联对象,而且是延迟加载。有时候这种关系延迟加载可能会严重影响性能,比如下面这个例子:
class User < ActiveRecord::Base
end
class Post < ActiveRecord::Base
has_many :replies
end
class Reply < ActiveRecord::Base
belongs_to :user
belongs_to :post
end
我们在查询某一个帖子的同时,希望取到所有回复以及回复者。
@post = Post.find(params[:id])
<%= @post.body %>
<hr />
<% @post.replies.each do |reply| -%>
<%= reply.body %><br />Post by: <%= reply.user.name %><hr />
<% end -%>
如果你查看日志,就会发现一大堆的查询,类似于:
SELECT * FROM users WHERE id = xx limit 1
这个对性能的影响还是很严重的,所以需要改进查询,在查询出reply的同时把user也查询出来。把它修改为:
@post = Post.find(params[:id], :include => {:replies => :user})
这次所有查询都在一条语句中进行了,不过某些情况下你可以会发现它反而会降低查询效率,原因在于本来只有1条的post记录也被扩展到多条了,这时候还是分开查询为好:
@post = Post.find(params[:id])
@replies = @post.replies.find(:all, :include => :user)
是的,这次总共只有2条语句,一般情况下效率都会提升许多。
使用find with :include可以提高效率,但尽量不要对一对多关系使用。如果只是一对一关系,那么即便是很多层的关联,效率也还不错。比如这样:
Street.find(1, :include => {:city => {:province => {:country => :continent}}})
有时我们还是要查询一些一对多关系,这时候也可以采用其它一些技巧,例如下面这个查询:
Comment.find(1, :include => {:user => {:replies => :post}})
我把它理解为:查询某一评论(comment),同时查出发表这一评论的用户发表过的回复帖子,以及这些帖子所回复的主题。当然这种查询可能是不合理的,只是想探讨一下如何优化这种查询。
由于数据库查询的效率往往比服务器处理要低,而且服务器很容易扩展而数据库集群则难以部署,所以我们还是要尽量减少查询次数,同时不增加查询数据量。
这里我的想法是把它分成2次查询:
@comments = Comment.find(:all, :include => :user)
user_ids = [0].concat(@comments.map(&:user).map(&:id))
replies = Replies.find(:all, :conditions => ["user_id in (?)", user_ids], :include => :post)
@user_replies = {}
replies.each {|r| @user_replies[r.user_id] ||= []; @user_replies[r.user_id] << r}
然后直接使用就可以了,在要显示某用户的回复及这些回复的主题时,只要把user.id作为key从@user_replies里提取。使用[0].concat是防止可能构造出一个空数组,查询时会生成一个非法SQL语句,这里也假设0是一个无效的ID值。
我曾经在一些查询中使用这个做法,结果数据库查询时间缩短了近10倍,整个action的处理效率也因此提高了4倍。
分享到:
相关推荐
8. **数据库设计**:合理设计数据库表结构,使用外键和索引来优化查询性能。考虑数据库的扩展性和一致性,例如使用JOINs来合并数据,而不是在应用层处理。 9. **安全**:遵循RESTful设计,利用Rails的安全特性,如...
这对于需要优化查询性能的开发者来说是一个有利的工具,但对那些不熟悉SQL的人来说可能学习曲线会比较陡峭。 在压缩包"occams-record-master"中,可能包含了Occam's Record库的源代码,包括README文件、示例代码和...
- 调整 NHibernate 的配置参数以优化查询效率。 8. **帮助文档** - 提供的 `.chm` 文件是 Castle ActiveRecord 的官方帮助文档,包含了详细的功能说明、示例代码和故障排查指南,是学习和解决问题的重要资源。 ...
- 如何优化查询性能。 - 如何利用ActiveRecord处理大量数据。 - 如何在复杂的应用场景下保持代码的可维护性。 #### 七、总结 《Pro ActiveRecord Databases with Ruby and Rails》是一本针对中级到高级Ruby on ...
Castle ActiveRecord是NHibernate ActiveRecord实现的一个版本,提供了额外的功能和方便性。它是一个AOP(面向切面编程)框架,能够自动管理对象的生命周期,包括事务、验证和持久化。 9. **最佳实践** 在实际...
综合这些信息,我们可以推断出这个Ruby库是一个专注于数据库查询和数据转换的工具,它帮助开发者将ActiveRecord查询结果转化为分析哈希,便于在各种图表库中进行数据可视化。对于Ruby on Rails开发者来说,这可以极...
在"ASP源码—实现ActiveRecord数据查询更新 v1.0.zip"中,我们可以推测这是一个实现了ActiveRecord概念的ASP库或框架,允许开发者更便捷地进行数据库查询和更新操作。以下是一些关于ASP和ActiveRecord模式的核心知识...
3. **数据库操作方法**:这些方法包括`Save()`(用于创建或更新记录)、`Delete()`(删除记录)、`Find()`或`Load()`(查询和加载记录)等。这些方法由 Castle ActiveRecord 提供,使得开发者无需编写SQL即可执行...
总之,`Ruby-marginalia`是提升ActiveRecord应用开发效率和可维护性的强大工具,通过在SQL查询中添加注释,它提供了宝贵的上下文信息,使开发者能够更有效地管理和优化数据库交互。在进行性能优化或者调试时,`...
然而,标准的ActiveRecord查询并不总是满足复杂的全文搜索需求。这时,`SearchCop`应运而生,它是一个强大的插件,旨在为ActiveRecord添加类似于搜索引擎的全文查询功能。 **SearchCop的核心特性** 1. **灵活的...
Java 敏捷持久层技术是现代软件开发中的一个重要组成部分,它简化了数据库操作,使得...虽然ActiveRecord在小到中型项目中表现出色,但对于大数据量、高并发的应用场景,可能需要更优化的解决方案,如MyBatis或JPA。
Ruby-pg-eyeballs是一个专门针对Ruby on Rails框架中ActiveRecord组件的工具,它能够帮助开发者深入理解并分析由ActiveRecord生成的SQL查询。在Ruby开发过程中,尤其是在处理复杂数据库交互时,这个gem显得尤为有用...
4. **查询API**:Castle ActiveRecord提供了强大的查询API,包括简单的属性查询、复杂的HQL(Hibernate Query Language)以及LINQ支持。这使得开发者可以方便地进行数据筛选、聚合、排序等操作。 5. **性能优化**:...
总结,这个主题主要展示了如何在SQLAlchemy中实现类似于Active Record的编程风格,包括如何定义模型、使用Session查询数据、实现嵌套加载以优化性能,以及通过重写`__repr__`方法和使用Mixins来提升代码的可读性和可...
ActiveRecord 查询优化嘘,别告诉任何人……但是你在过去 9 周中构建的所有 Rails 应用程序的数据库性能可能都非常糟糕! 为什么? 因为 Rails 使编写导致N+1 查询的代码变得非常容易。 N+1 是一个性能问题,在页面...
- **自定义查询**:虽然ActiveRecord提供了强大的查询功能,但在某些情况下可能需要编写原生SQL查询。 - **性能调优**:随着应用规模的增长,性能问题逐渐显现,需要采取措施进行优化。 #### 七、结论 《Pro ...
5. **表分区** - 对于大数据场景,`SchemaPlus`支持表分区,优化存储和查询效率。 6. **序列化** - 提供了更强大的序列化机制,可以序列化更复杂的数据结构。 7. **数据库兼容性** - 支持多种数据库系统,如MySQL...
1. **ActiveRecord查询优化**:避免N+1查询,使用`includes`预加载关联数据,或者使用`pluck`和`select`只获取必要的列。 2. **缓存策略**:利用Rails的页面、片段和动作缓存,或者使用Redis、Memcached等外部缓存...