我如何获得的Rails跃跃欲试负载计数?跃跃欲试、负载、如何获得、Rails

由网友(簡簡單單dē快樂)分享简介:这是涉及到一个问题,一年改变以前。This is related to a question a year and change ago.我就忍了,应该开箱的问题的一个例子,只要你有sqlite3的使用:https://github.com/cairo140/rails-eager-loading-counts-d...

这是涉及到一个问题,一年改变以前。

This is related to a question a year and change ago.

我就忍了,应该开箱的问题的一个例子,只要你有sqlite3的使用:https://github.com/cairo140/rails-eager-loading-counts-demo

I put up an example of the question that should work out of the box, provided you have sqlite3 available: https://github.com/cairo140/rails-eager-loading-counts-demo

git clone git://github.com/cairo140/rails-eager-loading-counts-demo.git
cd rails-eager-loading-counts-demo
rails s

我有一个更全面的写在资源库,但我一般的问题是这样的。

I have a fuller write-up in the repository, but my general question is this.

我怎样才能让Rails的渴望负荷数在全线最大限度地减少数据库查询的方式?

N + 1 的问题出现时,你使用 #COUNT 的关联,尽管有包括通过该协会#包括(:相关)在ActiveRelation。一种解决方法是使用 #length ,但是这个效果很好,只有当它被称为上已经加载了对象,更何况,我怀疑它复制的东西了Rails内部已经做了。另外,一个问题,使用 #length 的是,它导致了一个不幸的过载时,该协会没有被加载到开始和计数是你所需要的。

The n+1 problem emerges whenever you use #count on an association, despite having included that association via #includes(:associated) in the ActiveRelation. A workaround is to use #length, but this works well only when the object it's being called on has already been loaded up, not to mention that I suspect it duplicates something that the Rails internals have done already. Also, an issue with using #length is that it results in an unfortunate over-loading when the association was not loaded to begin with and the count is all you need.

从自述:

我们可以通过运行#length职位阵列(见附录),这已经是装在躲闪这个问题,但它会是不错的现成的数量为好。它不仅是更加一致;它提供了访问的,这并不一定需要的帖子被装载的路径。举例来说,如果你有一个部分,显示计数不管是什么,但一半的时间,部分被调用加载的职位和一半的时间没有了,你都面临着以下情形:

We can dodge this issue by running #length on the posts array (see appendix), which is already loaded, but it would be nice to have count readily available as well. Not only is it more consistent; it provides a path of access that doesn't necessarily require posts to be loaded. For instance, if you have a partial that displays the count no matter what, but half the time, the partial is called with posts loaded and half the time without, you are faced with the following scenario:   使用 #COUNT       N COUNT 样式的查询时,已经加载的帖子    N COUNT 样式的查询时尚未加载帖子    Using #count n COUNT style queries when posts are already loaded n COUNT style queries when posts are not already loaded   在零附加的查询时,已经加载的帖子    N * 样式的查询时尚未加载帖子    Zero additional queries when posts are already loaded n * style queries when posts are not already loaded

这些两种选择之间,不存在显性选择。但是,这将是很好的修改#COUNT推迟到#length或访问存储在幕后,使我们可以有以下情形一些其他的方式长度:

Between these two choices, there is no dominant option. But it would be nice to revise #count to defer to #length or access the length that is some other way stored behind the scenes so that we can have the following scenario:

  使用修订后的 #COUNT      在零附加的查询时,已经加载的帖子    N COUNT 样式的查询时尚未加载帖子    Using revised #count Zero additional queries when posts are already loaded n COUNT style queries when posts are not already loaded

那么,什么是正确的做法吗?有件事情我已经忽略了(非常有可能)?

So what's the correct approach here? Is there something I've overlooked (very, very likely)?

推荐答案

看来,最好的方式来实现这种设备可能是创建SQL视图(参考:这里和的这里)为所需的单独模型和孩子计数的对象;及其相关ActiveRecord模型。

It appears that the best way to implement this sort of facility might be to create SQL Views (ref: here and here) for the seperate model-and-child-count objects that you want; and their associated ActiveRecord models.

您也许能够成为的很聪明的,并使用子类的结合原始模型set_table_name:sql_view_name 保留所有的原始方法上的对象,甚至他们的一些关联。

You might be able to be very clever and use subclassing on the original model combined with set_table_name :sql_view_name to retain all the original methods on the objects, and maybe even some of their associations.

例如,假设我们要加上'Post.has_many:评论到你的榜样,像上面@祖宾的回答;再一个可能是能够做到:

For instance, say we were to add 'Post.has_many :comments' to your example, like in @Zubin's answer above; then one might be able to do:

   class CreatePostsWithCommentsCountsView < ActiveRecord::Migration
      def self.up
        #Create SQL View called posts_with_comments_counts which maps over 
        # select posts.*, count(comments.id) as comments_count from posts 
        #   left outer join comments on comments.post_id = posts.id 
        #   group by posts.id
        # (As zubin pointed out above.) 
        #*Except* this is in SQL so perhaps we'll be able to do further 
        # reducing queries against it *as though it were any other table.*
      end    
   end

   class PostWithCommentsCount < Post         #Here there be cleverness.
                                              #The class definition sets up PWCC 
                                              # with all the regular methods of 
                                              # Post (pointing to the posts table
                                              # due to Rails' STI facility.)

    set_table_name :posts_with_comment_counts #But then we point it to the 
                                              # SQL view instead.
                                              #If you don't really care about
                                              # the methods of Post being in PWCC
                                              # then you could just make it a 
                                              # normal subclass of AR::Base.
   end

   PostWithCommentsCount.all(:include => :user)  #Obviously, this sort of "upward
     # looking" include is best used in big lists like "latest posts" rather than
     # "These posts for this user." But hopefully it illustrates the improved 
     # activerecordiness of this style of solution.
   PostWithCommentsCount.all(:include => :comments) #And I'm pretty sure you 
     # should be able to do this without issue as well. And it _should_ only be 
     # the two queries.
阅读全文

相关推荐

最新文章