Gravatar

Geoff Evason

Posts Tagged ‘optimization’

The (insane) Importance Of Database Indices

Thursday, December 20th, 2007

One of the great things about Rails (especially for beginners) is that you need to know very little about database.

One of the bad things about Rails (especially for beginners) is that you need to know very little about database.

Through all of the literature I read while learning rails, I only have a vague recollection of databases indexes being mentioned. I started learning more about them recently because the performance of one of my apps was degrading over time, and literally, in about 2 hours, I increased the performance of my backend processing by 5x!!!

Intrigued? First – some background:

Most tables in rails (anything that has a model really) has a field ‘id’. This is the primary key of the database, and an index is created on this. I am a database rookie, but I know that an index is just like an index in a book. It’s extra info that the database stores so that it can find things more quickly.

Indices are not a concern when you get started, nor should they be. When your table gets to 1000s of entries, then they CAN become more important. It largely depends on how your app works.

Lets take a simplified example. Lets say you have an app that has sites and pages:


create_table "sites", :force => true do |t|
  t.column "permalink", :string
end

create_table "pages", :force => true do |t|
  t.column "site_id", :integer
end

Someone can view a site, and each site has pages:


class Site < ActiveRecord::Base
  has_many :pages
end

Because you want pretty urls you want someone to be able to go to www.myapp.com/<site.name>/<page.id>. The first thing you need to do that is


@site = Site.find_by_permalink(params[:id])

Of course, you are also going to need to have navigation for that site, so while rendering you have something like this


<div id="nav">
  <% for page in @site.pages %>
     <%# (do something with the page here) %>
  <% end %>
</div>

So what happens, when your someone tries to view a site?

Step 1: find_by_permalink: The database has to open every single ’site’ and check if the permalink matches.

Step 2: @site.pages: The database has to open every single page and check if the event_id field matches the id of the event that it is looking for.

When you have small numbers of rows, this isn’t a big problem. When you get 1000s of rows, looking through every site and every page gets slow, quickly.

So, the solution is to add an index. You add indices in Rails using migrations. You can create a migration like this:


class AddIndices < ActiveRecord::Migration
  def self.up
    add_index :sites, :permalink
    add_index :pages, :site_id
  end

  def self.down
    remove_index :sites, :permalink
    remove_index :pages, :site_id
  end
end

When you add those 2 indices, the database can now much more quickly find and retrieve the single Site object by permalink, and find and retrieve only the required Page objects rather than having to search the entire database for a match.

Doing this got my a 5x improvement in the speed of some of my more common actions, and literally took 2 hours.

You do need to be careful. Adding indices can slow down your performance because every time you insert, update, or delete rows, the database must also alter the index.

Some useful links:

http://therailsway.com/2006/11/21/tracks-part-4

http://weblog.jamisbuck.org/2006/10/23/indexing-for-db-performance

http://www.websitedatabases.com/database-index.html

There are probably good ways of benchmarking this. After testing locally, I copied my live data to my staging area, added the indices, ran a few actions, and compared the logs from before/after the migration. In my case, some actions got a bitter slower, but those were uncommon ones. My most common actions got 5x faster!! Have a look at the following graph. The red lines show the % of time for an action after adding the indices. Above 100% means the action got slower. Below means it got faster. You an see most actions got a lot faster!

Effect of Database Index

YSlow On Rails

Wednesday, October 17th, 2007

I gave a talk recently on how to improve the front end performance of a rails app using YSlow as a tool to measure said performance.

10 Best Tools For Testing, Debugging, & Optimizing Websites

Sunday, September 23rd, 2007

I’ve learned a lot about web apps in recent months, so I thought I summarize what I have found to be the most useful resources in terms of helping me do things well.

1. Firebug: http://www.getfirebug.com Firebug is a plugin for firefox that, well, lets you see any detail about a web page that you could conceivably what to see. I’ve only ever heard good things about, and the accolades are very well deserved. So far I’ve used it for:

  1. Analyzing the DOM
  2. Stepping through (and setting break points) in Javascript
  3. Viewing Javascript errors
  4. Viewing Styles

To be honest – I think I’ve only just scratched the surface.

2. Firefox Web Developer Toolbar https://addons.mozilla.org/en-US/firefox/addon/60 There may be some overlap between this and firebug, but I use both. I find this particularly good for debugging styling. ‘View Style Information’ is killer. It is also very useful for testing your site with javascript or cookies disabled.

3. YSlow http://developer.yahoo.com/yslow/ This is actually a plugin for firebug (yeah – a plugin for a plugin). It analyzes a page using 13 metrics (all with very details descriptions that are linked to), and gives a grade for each one, as well as an overall grade. I took my score from 33 to 60+ but my site is so much more responsive than it used to be. The biggest gain was simply by putting all the javascript at the end, so the page visually loads so much faster. I’m moving to a dedicated server at present, and will then be able to increase the grade even more.

4. Total Validator https://addons.mozilla.org/en-US/firefox/addon/2318 This basically just redirects you to a online html validator, though the pro version does it locally I believe. As I understand, valid HTML is good for both SEO & cross browser compatability (well – except for IE).

5. Selenium http://www.openqa.org/selenium/ Selenium uses javascript to test drive your app. I wrote about it before. Backend testing is easy in rails, but there is no way to test the user interface, especially for javascript heavy sights. Selenium is the answer. With the IDE you can even record actions and run them as test later :-)

6. IE Developer Toolbar (ie toolbar download) This is basically a combination of firebug & the firefox web developer toolbar. It’s pretty good, and I’ve used it several times to track what was happening in IE. It only works with IE7 though – which is too bad since most of my problems are with IE6…

7. ScreenGrab http://www.screengrab.org/ This firefox plugin lets you render a page (visible portion or whole thing) to an image file. One note – it allows you to save with a .jpg extension, but really saves in .png format. This caused me problems when I was trying to do something with an image that needed to really be in .jpg format…

8. Quick Locale Switcher https://addons.mozilla.org/en-US/firefox/addon/1333 This is ideal for testing an app with localization. I’ve only played around with it quickly as I’m not doing localization yet, but it will come in very handy when I do.

9. Site Report Card http://www.sitereportcard.com This is an online tool that checks a number of things on your site, such as inclusion in search engines, html validity, spelling, links, etc.

10. Love Love Okay – so I really only have 9 tools – but 10 just seems like a better number for a title… Love is good though. Spread the love and all will be well…

So there’s my opinion of the top 10 tools for testing, debugging, and optimizing web apps. most of them are firefox add-ons, but I would recommend against getting too dependent on firefox. The <problem> with firefox is the lack of bugs… Rotate browsers when developing…