views:

643

answers:

3

I'm having approx. 200K rows in a table tb_post, and every 5 minutes it has approx. 10 new inserts.

I'm using following query to fetch the rows -

SELECT tb_post.ID, tb_post.USER_ID, tb_post.TEXT, tb_post.RATING, tb_post.CREATED_AT,
       tb_user.ID, tb_user.NAME 
FROM tb_post, tb_user 
WHERE tb_post.USER_ID=tb_user.ID 
ORDER BY tb_post.RATING DESC 
LIMIT 30

It's taking more than 10sec to fetch all the rows in sorted fashion.

Following is the report of EXPLAIN query:

id select_type  table   type  possible_keys  key    key_len  ref   rows   Extra
1   SIMPLE   tb_user  ALL  PRIMARY   NULL    NULL   NULL   20950   Using temporary; Using filesort
1   SIMPLE   tb_post  ref  tb_post_FI_1  tb_post_FI_1  4    tb_user.id  4

Few inputs:

  • tb_post.RATING is Float type
  • There is index on tb_post.USER_ID

Can anyone suggest me few pointers about how should I optimize this query and improve its read performance?

PS: I'm newbie in database scaling issues. So any kinds of suggestions will be useful specific to this query.

+1  A: 

What happens if you take the ORDER BY off, does that have a performance impact? If that has a large effect then maybe consider indexing tb_post.RATING.

Karl

Karl
I cannot take off the ORDER BY clause. I need to show the results based on its popular ratings.
Aditya
@Aditya - did you try adding the index on tb_post.rating?
warren
+3  A: 

You could try to index tb_post.RATING: MySQL can sometimes use indexes to optimize ORDER BY clauses : http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html

If you're trying to aggregate data from different tables, you could also check which type of join ( http://en.wikipedia.org/wiki/Join_(SQL) ) you want. Some are better than others, depending on what you want.

Xr
"Sory for the URLs, I'm not allowed to post hyperlinks..." - that's 'fixable' :-)
VolkerK
tb_post.RATING is a Float type. So do indexes work fine on Float type columns? Also, RATINGs do change quite frequently when someone votes that post. So everytime someone votes, MySQL will need to build indexes again. If the voting rate is quite frequent, then building indexes everytime can be expensive, right?I tried adding indexes on RATING, and now first time it takes more than 10secs, but next time, if there are no new votes, then it takes 1-2 secs. But as soon as someone votes, it again takes lot of time to fetch the same page.So please advice.
Aditya
How do you create your index and, more importantly, update a rating? I just checked with a 200k rows test table (id, rating, text, user_id): creating the index takes 3 seconds no matter what the index contains (and, in particular, using VolkerK's way). Updating a single row to change the rating takes a few millisecs, as it should. You musn't create an index every time you update: instead, your run a normal UPDATE query and let MySQL update its index. If you are sure you do the update properly (UPDATE, not CREATE INDEX), check that the culprit is indeed MySQL, not a caching system or whatever.
Xr
+4  A: 

You need an index for tb_post that covers both the ORDER BY and WHERE clause.

CREATE INDEX idx2 on tb_post (rating,user_id)

=> output of EXPLAIN SELECT ...ORDER BY tb_post.RATING DESC LIMIT 30

"id";"select_type";"table";"type";"possible_keys";"key";"key_len";"ref";"rows";"Extra"
"1";"SIMPLE";"tb_post";"index";NULL;"idx2";"10";NULL;"352";""
"1";"SIMPLE";"tb_user";"eq_ref";"PRIMARY";"PRIMARY";"4";"test.tb_post.USER_ID";"1";""
VolkerK