Ruby On Rails中如何避免N+1问题

 更新时间:2014年07月04日 09:03:04   投稿:hebedich  
select语句的数目太多,需要频繁的访问数据库,会影响检索性能。如果需要查询n个Customer对象,那么必须执行n+1次select查询语句。这就是经典的n+1次select查询问题。

N+1问题

N+1问题是数据库访问中最常见的一个性能问题,首先介绍一下什么是N+1问题:

举个例子,我们数据库中有两张表,一个是Customers,一个是Orders。Orders中含有一个外键customer_id,指向了Customers的主键id。

想要得到所有Customer以及其分别对应的Order,一种写法是

SELECT * FROM Customers;

对于每一个Customer;

SELECT * FROM Orders WHERE Orders.customer_id = #{customer.id}

这样我们实际对数据库做了N+1次查询:选择所有Customer一次得到N个Customer,对于N个Customer分别选择其对应的Order一共N次。所以,一共执行了N+1次查询,这就是N+1问题

N+1问题的一般解决方法

使用Left Join一次性取出所有数据:

SELECT * FROM Customers LEFT JOIN Orders on Customers.id = Orders.customer_id

这样虽然取出的数据相对多一些,但是只需要一次执行

Rails中的N+1问题

因为Rails使用ActiveRecord访问数据库。所以,它的N+1问题暴露的不是那么明显。

假设我们有两个ActiveRecord:Customer、Order。

Customer has_many :orders

Order belong_to :customer

一般我们获取所有Customer的方法是:

customers = Customer.all

如果我们后面紧跟着

customers.each { |customer| puts customer.orders.amount }

这样就会产生N+1问题,因为在获取所有Customer的时候,是没有去取orders的。然后在后面each遍历的时候,就会挨个的取orders,这就构成了rails中的N+1问题。

Rails中的N+1问题解决方法

customers = Customers.includes(:orders)

这样就在读取customers的时候也一次性的把orders都取出了。

更多

并不是对于所有的涉及到外键关联,一对多的问题都会产生N+1问题,这还是要取决于你的业务。比如你的方法在执行时,只有很少的可能会去获取customer对应的orders,那就保持默认的lazy方式去就行了。强制eager去取反而得不偿失。

相关文章

  • Ruby日期时间的比较,日期转换等时间日期处理方法大全

    Ruby日期时间的比较,日期转换等时间日期处理方法大全

    这篇文章主要介绍了Ruby的日期时间处理方法与函数,日期时间和字符串、数值之间的转换,日期时间的比较需要的朋友可以参考下
    2022-04-04
  • 使用Ruby程序实现web信息抓取的教程

    使用Ruby程序实现web信息抓取的教程

    这篇文章主要介绍了使用Ruby程序实现web信息抓取的教程,本文来自于IBM官方网站技术文档,需要的朋友可以参考下
    2015-04-04
  • ruby实现github第三方认证

    ruby实现github第三方认证

    GitHub在用户认证过程中采用了双匙机制,在双匙加密机制中,只有合法用户才拥有私匙,只要GitHub在收到请求时可以证明提交请求的客户端上拥有该私匙,即可以确认该操作是由合法用户发起的。我们通过ruby来简单模拟下吧。
    2015-06-06
  • ruby使用restclient上传服务器本地文件示例

    ruby使用restclient上传服务器本地文件示例

    这篇文章主要介绍了ruby使用restclient上传服务器本地文件示例,需要的朋友可以参考下
    2014-05-05
  • Ruby on Rails中Rack中间件的基础学习教程

    Ruby on Rails中Rack中间件的基础学习教程

    Rack是一个连接Ruby程序与服务器程序之间的中间件,甚至可以说Rails也是在Rack的基础上建立起来的,这里我们就来为大家带来Ruby on Rails中Rack中间件的基础学习教程
    2016-06-06
  • 详解Ruby中的方法概念

    详解Ruby中的方法概念

    这篇文章主要介绍了详解Ruby中的方法概念,包括方法的自定义和返回值等基础知识,需要的朋友可以参考下
    2015-05-05
  • Ruby中的Mechanize的使用教程

    Ruby中的Mechanize的使用教程

    这篇文章主要介绍了Ruby中的Mechanize的使用教程,Mechanize一般用来抓取网页,可以模拟点击事件、表单提交提交等操作行为,需要的朋友可以参考下
    2015-01-01
  • Ruby 面向对象知识总结

    Ruby 面向对象知识总结

    这篇文章主要介绍了Ruby 面向对象的的相关资料,文中讲解非常详细,实例代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • 详解Ruby设计模式编程中对单例模式的运用

    详解Ruby设计模式编程中对单例模式的运用

    这篇文章主要介绍了Ruby设计模式编程中对单例模式的运用,讲到了包括对Singleton模块的使用,需要的朋友可以参考下
    2016-03-03
  • Ruby学习笔记一

    Ruby学习笔记一

    学习ruby有段时间了,记录下自己的学习心得并分享几个例子给大家
    2014-07-07

最新评论