class Parent < ActiveRecord::Base
has_many :children
end
class Child < ActiveRecord::Base
belongs_to :parent
end
Which is correct. Then, to keep things looking pretty, when you want a scoped subset of a given parent's children, you probably write something like this
class Parent < ActiveRecord::Base
has_many :children
end
class Child < ActiveRecord::Base
belongs_to :parent
named_scope :who_can_drive,:conditions=>"age >= 16"
end
parent = Parent.first
children = parent.children.who_can_drive
Which is well and good. Except when you care about performance. You see, I did something like this in my production application. Both fields on the child model are indexed (the foreign key, and the field used for searching by), but guess which one gets used first? If you know your named scopes, you know that in practice the named scope that is APPLIED LAST in the chain is used first in the query, and that's the one MySQL decided to use as the primary index.
Now if a parent has 2 or 3 children, but it's in a table of 15,000,000 kids between the ages of 14 and 21, which index do you think will produce the smaller set to scan? The one that narrows it down to only the 2 or 3 children of that parent and then checks their age, or the one that narrows it down to the 7 million children over the age of 16 and then checks their parent?
So to keep my server from crashing and burning, I've started writing my code like this:
class Parent < ActiveRecord::Base
has_many :children
end
class Child < ActiveRecord::Base
belongs_to :parent
named_scope :who_can_drive,:conditions=>"age >= 16"
named_scope :belonging_to,lambda{|parent| {:conditions=>{:parent_id=>parent.id}}}
end
parent = Parent.first
children = Child.who_can_drive.belonging_to(parent)
I don't like it, but it sure improved my scores on my newrelic monitoring graphs. Anybody have a more elegant solution to this problem?

No comments:
Post a Comment