【问题标题】:How do you do eager loading with limits?您如何进行有限制的急切加载?
【发布时间】:2011-09-22 14:03:59
【问题描述】:

在预先加载的文档中指出:


如果您使用指定的 :limit 选项急切加载关联,它将被忽略,并返回所有关联的对象:

class Picture < ActiveRecord::Base
  has_many :most_recent_comments, :class_name => 'Comment', 
                                  :order => 'id DESC', :limit => 10
end

Picture.find(:first, :include => :most_recent_cmets).most_recent_cmets # => 返回所有关联的 cmets。


如果是这种情况,那么实现加载“限制”的最佳方法是什么?

假设我们急于将最后 10 篇博文加载到博客的首页,我们显然不希望它们全部如此,是否应该指定博文集合的限制和顺序?

除此之外,是否可以对深度加载的元素指定相同的条件 - 例如,仅在每篇博文中显示前三个 cmets?

Blog.find(:blog_id, :include => {:posts => :comments } )

【问题讨论】:

标签: ruby-on-rails optimization activerecord eager-loading


【解决方案1】:

你可以使用这个结构: Picture.find(:first, :include =&gt; :most_recent_comments).most_recent_comments.limit(10)

AR guide中查看更多信息

【讨论】:

  • 您描述的模式不限制原始查询,只限制从它返回的数据。挑战在于限制原始查询,使其不会将所有博客文章加载到内存中
【解决方案2】:

我相信这是因为 sql 中的 LIMIT 命令不能很好地转换为您要执行的操作。 LIMIT 将限制查询返回的总行数。不过,您并没有尝试这样做。您正在尝试限制为返回的每张图片连接的行数。为了达到这种效果,您必须使用一些复杂的 SQL,如果您的表很大,这可能很难优化。那时我会考虑你为什么要限制急切加载的行。

如果预先加载的最大 cmets 数量是可管理的(

如果您只加载 10 个帖子,我会考虑根本不急切加载。我不希望额外的 10 个查询会大大降低速度,而且它们添加的时间,您可以通过尝试其他优化技术(例如缓存)来弥补。

您应该让示波器为您完成脏活,而不是关联。这促进了可重用性、可维护性和可读性。示例:

Class Picture < ActiveRecord::Base
  has_many :comments, :order => 'id DESC' do
    def recent
      limit(10)
    end
  end
end

这样.comments 在你需要的时候就在那里,你也可以像这样缩小范围:

@picture.comments.recent

【讨论】:

    【解决方案3】:

    我使用 will_paginate 来帮助我快速加载(using includes),因为我必须一次性加载许多相关模型没有使用limit

    Image.includes(:user,:tags).where("user_id !=?",current_user.id).paginate(:page => params[:page], :per_page => 15)
    

    OR(不带 will_paginate(使用 limit

    Image.includes(:user,:tags).where("user_id !=?",current_user.id).limit(30).order("created_at ASC")
    

    ...试一试..希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-09
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      • 1970-01-01
      • 2017-05-30
      • 2019-05-19
      相关资源
      最近更新 更多