Getting ActiveRecord objects by ID
I'm trying to speed up a rails app here, and I've been making some assumptions that I've realised may not actually be true.
Specifically, if I have a list of IDs, I've been assuming that
list_of_ids.map{|id| Model.find(id) }
is going to be slower than
Model.find( list_of_ids )
Presumably, the latter will only make one SQL call to fetch all the objects, but the former will make a call per ID. This is because I'm used to perl, where the ORMs are stupid, the language is fast, and the DB is always the bottleneck.
But the sort of SQL produced by the supposedly slower approach is much more cacheable. The supposedly faster approach will tend to generate a different SQL query every time, whereas a sufficiently smart cache layer could intercept the SQL calls of the later approach and just hand back the models.
Initial benchmarking seems to have the one-SQL-call approach faster anyway. It does turn out to have a disadvantage, though - Model.find( ids )
doesn't return objects in the same order that the IDs were in, whereas the map
approach does. That's fairly easy to fix, though:
class ActiveRecord::Base
class << self
def find_in_order( ids )
# return all instances with the passed ids, in the order that the ids are in
objects = self.find( ids )
objects = objects.sort_by{|o|ids.index(o.id)}
return objects
end
end
end