美文网首页
简述n+1问题

简述n+1问题

作者: biubiudog | 来源:发表于2018-11-13 14:00 被阅读0次

在Rails ActiveRecord中,常会嵌套遍历很多orm模型。
如:常用的一对多(用户和文章)模型中

    class User
      has_many :articles
    end

    class Article
      belongs_to :user
    end

如果有十个用户,那么查询每个用户对应的文章需要查询11次。

     User.all.map{|user| user.articles}
    select * from users
    select * from articles where user_id = 1
    ...
    select * from articles where user_id = 10

为了解决这个问题,一般的解决方案是:

1. 预加载

使用includes, preload, eager_load

    User.includes(:articles).map{|user| user.acticles }
    select * from users 
    select * from articles where user_id in (1..10)

只需要2条查询语句

includes 和preload 、eager_load的区别

Rails 提供了4种方式来加载关联表的数据:

  • proload:使用一条附加的查询语句来加载关联数据,总是会生成两个sql语句。

User.preload(:articles)是默认的User.includes(:articles)加载方式。

加入查询条件时使用preload会报错:

User.preload(:articles).where("articles.content = '123' ")
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: articles.content: SELECT  "users".* FROM "users" WHERE (articles.content = '123' ) LIMIT ?

includes加入查询条件不会报错

User.includes(:articles).where("articles.content = '123' ")

而preload的条件中加入users表的查询条件则没有问题:

User.preload(:articles).where("users.name = '123' ")
  • eager_load
    eager_load使用left outer join进行单次查询,并加载所有关联数据。
  • joins
    joins使用inner join来加载关联数据

2.使用Goldiloader

(参考 https://github.com/salsify/goldiloader
安装 gem 'goldiloader'
默认情况下,所有关联在首次访问时都会自动加载。
你可以手动添加代码auto_include,禁止自动预先加载:
User.auto_include(false)
在关联关系中使用proc来禁止自动预先加载。

      class  User < ActiveRecord::Base
          has_many :articles, ->{ auto_include(false) }
      end     

fully_load选项可用于强制ActiveRecord完全加载关联(并执行任何必要的自动切换加载)

class  Blog <ActiveRecord :: Base 
  has_many :posts,fully_load: true 
end

相关文章

  • 简述n+1问题

    在Rails ActiveRecord中,常会嵌套遍历很多orm模型。如:常用的一对多(用户和文章)模型中 如果有...

  • Mybatis延迟加载及二级缓存简明教程

    延迟加载 延迟加载处理的是N+1性能问题,所谓N+1性能问题指的是映射集合(resultMap)内存在级联时,我们...

  • rails基础-解决 n+1

    N+1问题是新手常犯的一个问题,这里记录如何解决rails项目中的N+1问题 rails 支持的关联 Active...

  • GraphQL(八):GraphQL集成DataLoader

    N+1问题 首先来看看什么是N+1问题,假设我们有如下模型: 然后我们有这样的查询: 会得到类似下面的结果: 根据...

  • 第8课 GraphQL集成DataLoader

    N+1问题 首先来看看什么是N+1问题,假设我们有如下模型: 然后我们有这样的查询: 会得到类似下面的结果: 根据...

  • LeetCode之N-Repeated Element in S

    问题:In a array A of size 2N, there are N+1 unique elements...

  • Mybatis N+1问题

    Mybatis是很流行的数据库中间件,对于一对多等复杂关系配置容易产生N+1的问题,下面我们来了解下。 关联嵌套查...

  • 简述“拖延问题”

    拖延从根本上说并不是一个自我时间管理的天问题,也不是一个道德层面的问题,而是一个心理问题,此外它还受到一些...

  • Python Django 使用日常问题记录

    django N+1 问题解决:https://my.oschina.net/oncereply/blog/268...

  • Java实现全排列

    ①假设全排列函数为f(n)=n!,那么可以立刻知道f(n+1)=(n+1)Xn!=(n+1)*f(n),因此可以利...

网友评论

      本文标题:简述n+1问题

      本文链接:https://www.haomeiwen.com/subject/pbecfqtx.html