Speeding up ActiveRecord with Hashes, Take 2
A few weeks ago, I posted about the release of my gem, hash_extension, which makes Ruby hashes act a little more like plain old objects. That’s a good thing, because ActiveRecord requests that return hashes instead of full-blown ActiveRecord objects are about 50% faster. 50% is not a performance tweak — it’s basically the best thing that’s ever happened to ActiveRecord.
In version 0.0.1, the only way to get back hashes from ActiveRecord for use with hash_extension was to use select_all:
Foo.connection.select_all("select * from foo")
In the docs for hash_extension I put out a call for someone to extend ActiveRecord itself to return hashes from more natural, ActiveRecord-esque methods. Elliot Laster answered that call, and now, in version 0.0.2, find_as_hashes and find_by_sql_as_hashes are now available:
Foo.find_as_hashes(:all)
Foo.find_as_hashes(:first)
Foo.find_as_hashes(:all, :conditions => "bar = 'baz'")
Foo.find_by_sql_as_hashes("complex sql goes here")
To learn more about the gem and to download, go here.

I noticed that http://pennysmalls.com/ also has a gem that, when used in conjunction with this one, results in even more memory speed up. Nice :)
-R
You may want to advertise your gem on rails talk :)
A nicety is that you’re able to ‘intertwine’ this with AR itself.
a = School.find(:first)
a.programs.find_as_hashes(:all) # this one. Ahh
Thank you!
-R
Perhaps another nicety would be something like
a = Model.find_as_hashes(:all)
a[22].to_ar # creates and instantiates an ar for this row [costly], so you can use its nice functions for special cases.
Thoughts?
-R
I think by that time you’ve lost the information regarding what the class was, so it could be difficult to do something like this without adding overhead to the original find_as_hashes call.
In general I think this is only useful for situations where you don’t need the AR layer, like in queries aimed at display as opposed to queries aimed at database modification. I think the general solution is “Make ActiveRecord more efficient,” which someone did do for the 1.2.x series, but the patches were lost on the way to 2.0.
were they related to these? http://blog.codefront.net/2008/02/13/living-on-the-edge-of-rails-7-improved-activerecordbaseattributes-time-zone-support/ is there more that lacks?
as mentioned somewhere else, I wonder if this in combination with http://railsexpress.de/blog/articles/2006/10/05/make-ruby-mysql-create-less-garbage would be…even better :)
Just a thought.
-R
Latest thought: combine all_hashes with a klass.allocate and ‘circumvent’ AR to create AR objects–but in a far far faster way. Then do it “always” if possible [reverting to old school if impossible]. Replace AR.find with it. That would be fast.
And then do the heavy lifting in C, possibly intertwining it with mysql_use_result and mysql_fetch_row.
Wish me luck!
-=R