Removing :include option from count query when it's possible
Reported by Denis Barushev | March 6th, 2008 @ 03:56 PM
In http://dev.rubyonrails.org/chang... was introduced new preload query strategy for eager :includes. Now Rails Edge uses one SELECT query per table (one for model table and one for each include table) instead a monster query with joins if it's possible. This strategy automatically are not used when there are conditions for included tables or something else (I'm not ruby/rails hacker yet):
activerecord/lib/active_record/base.rb:1242
if include_associations.any? && references_eager_loaded_tables?(options)
records = find_with_associations(options)
else
records = find_by_sql(construct_finder_sql(options))
if include_associations.any?
preload_associations(records, include_associations)
end
end
For example:
class Post < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
end
Post.find :all, :include => :comments
SELECT * FROM "posts"
SELECT comments.* FROM "comments" WHERE (comments.post_id IN (1,2))
Post.find :all, :include => :comments, :conditions => "posts.id > 1"
SELECT * FROM "posts" WHERE (posts.id > 1)
SELECT comments.* FROM "comments" WHERE (comments.post_id IN (2))
Post.find :all, :include => :comments, :conditions => "comments.id" > 1
SELECT "posts"."id" AS t0_r0, "posts"."title" AS t0_r1, "posts"."created_at" AS t0_r2, "posts"."updated_at" AS t0_r3, "comments"."id" AS t1_r0, "comments"."body" AS t1_r1, "comments"."post_id" AS t1_r2, "comments"."created_at" AS t1_r3, "comments"."updated_at" AS t1_r4 FROM "posts" LEFT OUTER JOIN "comments" ON comments.post_id = posts.id WHERE (comments.id > 1)
Post.paginate, :include => :comments
are two calls with some additional params(:offset, :linit) in fact:
Post.find, :include => :comments
Post.count, :include => :comments
But count method doesn't use this eager strategy. This is logically.
When I use paginate method with :include option, count method generated by it ALWAYS are invoked with param when it doesn't need.
For example,
Post.paginate :include => :comments, :page => 1
generates queries:
SELECT * FROM "posts"
SELECT comments.* FROM "comments" WHERE (comments.post_id IN (1,2))
SELECT count(DISTINCT "posts".id) AS count_all FROM "posts" LEFT OUTER JOIN "comments" ON comments.post_id = posts.id
but, in this case, last query may be:
SELECT count(*) AS count_all FROM "posts"
Main task is modify WillPaginate::Finder::ClassMethods#wp_count for distinguishing when it should add "inlude" to "excludes" array. I can't do that. May be anybody can examine how that works in 'find' method?
Comments and changes to this ticket
-
Denis Barushev May 15th, 2008 @ 12:02 PM
- → Title changed from "#paginate :include => something": removing joins from count query when it's possible to [PATCH] Removing :include option from count query when it's possible
I've done this. See patch.
-
Mislav May 16th, 2008 @ 03:27 AM
- → State changed from new to open
- → Title changed from [PATCH] Removing :include option from count query when it's possible to Removing :include option from count query when it's possible
This looks good, but next time please make a test :)
Also, with Lighthouse "patch" tag we don't need "[PATCH]" in subject anymore (that was a Trac thing).
Thanks!
-
Denis Barushev May 16th, 2008 @ 03:48 AM
I now about test, but there are some problems. This patch is about internals of #wp_count. I dunno how to test this. Test generated query is not good idea and I also dunno how to do this. May be it's good time for extracting #prepare_count_options from #wp_count?
-
-
Peter September 3rd, 2008 @ 10:05 AM
- → Tag changed from to count patch will_paginate
I just applied this patch but it is still doing the include in the count_all breaking my query because it's also doing an INNER JOIN duplicating a table name.
-
Peter September 3rd, 2008 @ 10:15 AM
Nevermind, it was part of my model association. I actually don't need the patch, thanks.
-
Mislav September 12th, 2008 @ 05:07 PM
- → State changed from open to resolved
This has been long resolved (fix present in both master and agnostic branch)
Please Login or create a free account to add a new comment.
You can update this ticket by sending an email to from your email client. (help)
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
