On Thu, Jan 26, 2012 at 6:37 PM, Peter Vandenabeele
<pe...@vandenabeele.com>wrote:

> On Thu, Jan 26, 2012 at 6:15 PM, Linus Pettersson <
> linus.petters...@gmail.com> wrote:
>
>> Hi
>>
>> I tested to remove the .order(...) part and indeed, the query time goes
>> down to ~100ms. However, it doesn't help to add indices, at least not as I
>> did :)
>>
>> add_index :categories, :name
>> add_index :subcategories, :name
>>
>> Did some more testing and if I keep the .order... but don't join the
>> products table I get a query that runs at about ~55ms. So the bottleneck
>> seems to be the products table.
>> The query that I'm running looks like this:
>>
>> Category.eager_load(:subcategories)
>>              .joins("INNER JOIN products AS p ON resellercategories.id =
>> p.resellercategory_id")
>>              .order("categories.name ASC, subcategories.name ASC")
>>
>> (Skipping the gender here...)
>>
>> What I have is Categories and Subcategories. They are related to each
>> other through a Resellercategories table. Products are related to
>> Resellercategories.
>> So, the reason that I want to join the products as well is because I only
>> want to show categories and subcategories that actually have some products
>> (there are some empty categories/subcategories still).
>>
>> So the above query is what we came up with in another thread here in the
>> group.
>>
>> - Maybe there is a better way to check if a category/subcategory has
>> products without joining the entire products table?
>>
>
>
> It is possible to add a :counter_cache , but then you need to make sure you
> use the proper methods for each product that you add or remove from the
> association.
>
> Alternative to the default counter cache (from Rails), you could build
> your own
> logic as in:
>
> * has_male_products
> * ...
>
> changing you query to  ...
>
> Category.eager_load(:subcategories).
>                where(:has_male_products => true).
>                order(...)
>
> Then you would need to set the cache on the appropriate categories in
> an after_save on the product you are
> creating/updating/deactivating/(deleting ?).
>
> Both ideas would probably be faster for querying, but certainly more
> complex for making sure that cache is always correct.
>

Sorry to reply to my own post.


TL;DR  Is there pagination? Then a smaller set may return much faster.


I was thinking over my reply and may have forgotten a fundamental
aspect ... If you say 2200 categories, 8000 products.

How many entries does you query return ?
(replace .add with .count at the end).

How many do you need ?

What happens when you add .limit(20) to your query ?

By which "primary object" do you want to sort and paginate ?
(I will assume 'Product' in the discussion below).

With the includes that are currently implemented, you may
have to redo the whole query into 2 qeuries ...

1) for fetching the "primary objects"
(e.g. exactly 20 Products, no additional "has_many" data, because
that would increase the number of returned rows for 1 product and
make proper pagination in the database impossible; including
"belongs_to" here is no problem)

2) a second query for fetching eventual "has_many" data
on those 20 "primary products" (is that "Reification" ?)

If the performance problem could be solved by taking the
pagination into account, that would be a _much_ better
solution that building cache columns in this early phase
of your project.

HTH,

Peter

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to 
rubyonrails-talk+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to