美文网首页
简述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问题

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