Do it the simple way..

We had a call from a client for whom I have built my first "commercial" Rails application. The client was telling the pages on blog part of their site started loading pretty slow.

After some quick investigation, I found out that it was somehow related to the access logging part of the application. Monitoring the SQL requests, I noticed requirest like "select * from accesses where accesses.site_id=1" taking huge time to get processes (well of course..). And I don't remember I was writing selections for all access records for a particular site anyways.

So who (or what?) was doing these huge selections? Turned out it was a pretty harmful code inside the Post class (which represents a blog post):

def log_access()
oneAccess = Access.new()
self.accesses << oneAccess
self.site.accesses << oneAccess
end

This just created a new access record and then attaches it to site, and to the post's accessses list. Well that's fine, and attaching access to the post's accesses list is actually pretty fast, but when it comes to the code:

self.site.accesses << oneAccess

things start getting hairy.. Basically, a post site's accesses are being completely read into memory, and THEN a new access record is attached to the list. And that's what generated the forementioned "select * from accesses where accesses.site_id=1" queries.

Fix is pretty easy of course, now that I know Rails better than few years ago ;)

def log_access()
oneAccess = Access.create(:post_id => self.id, :site_id => self.site_id)
end

So, the lesson is  – always be careful about making things the "smart" way, unless you understand what actually is going under the hood…

Leave a Reply