Archives for: December 2005, 28

12/28/05

Permalink 11:32:57 pm, Categories: Linux, 636 words   English (US)

Diagnosing MySQL load

Recently I looked at a client webserver where there were lots of MySQL processes eating up quite a bit of CPU. It's a fairly high traffic site, however when I see mysqld processes staying at 80-90% for more than a few seconds, that tells me something is wrong. It's usually an indication that either they are using some very inefficient queries, do not have the proper indexes, or the tables are getting too large.

So let's see how to debug this. First thing is by the looks of the processes, there must be 1 or 2 queries that are pegging the CPU, and we need to find out what queries are taking long. I started up the mysql client and did a 'show status':

show status;
...
| Slow_queries             | 12256     |
...

Hmm, lot's of slow queries. but that number isn't increasing rapidly. I believe this shows very slow queries only. Next I did a 'show processlist' a few times until something showed up:

show processlist;
...
| 2721 | web  | localhost | development | Query   |    0 | Copying to tmp table |
 SELECT DISTINCT wheel.make FROM inventory LEFT JOIN wheel ON
 inventory.id=wheel.id WHERE status="act |
...

Usually, if you see a query on 'show processlist' consistently, that query is probably unoptimized and taking a long time. The above only showed me part of the query, and I needed to find the whole query to test it. Now I could go digging in the client's source code, but it would be a waste of time trying to find the culprit query. The best way is to enable MySQL logging. MySQL is such a lightweight DB, restarting it usually goes unnoticed even on high traffic webservers. I added to /etc/my.cnf:

[mysqld]
log=/var/log/mysqld/mysqld.log

And made sure to create that logfile writable by the mysql user (it won't log it if it doesn't have the right permissions). Next I find the query I'm looking for:

SELECT DISTINCT diameter
FROM inventory
LEFT JOIN wheel_fitment ON wheel_fitment.wheel=wheel.id
LEFT JOIN wheel ON wheel_fitment.wheel=wheel.id
WHERE status="active" AND vehicle=4566  AND price!=0 AND
wheel_fitment.type="all"
ORDER BY diameter

Ok, I'm not too familiar with the multiple left joins, but I do know what a join is. I run this query manually and it takes anywhere from 6 to 10 seconds to return results. That's definitely too long for a query to take, and the tables are not even that big! Now is when you try to take everything out of the query except the bare necessity that makes it slow. I ended up with:

SELECT DISTINCT diameter 
FROM inventory
LEFT JOIN wheel ON wheel_fitment.wheel=wheel.id
LEFT JOIN wheel_fitment ON wheel_fitment.wheel=wheel.id
WHERE vehicle=4566

Now I needed to know something about these tables. As sysadmins, we usually come in the picture when something has gone wrong, and we really played no part in the development of the system we are diagnosing. I wanted to know whether there were indexes on the tables. I did 'show create table wheel' as well as wheel_fitment and inventory. They all seemed to have proper indexes on the fields being used in the query. Hm what next? Well the double 'LEFT JOINs' looked kinda wierd to me, they are just swapped. The resulting set if I take out the 'DISTINCT' is something like 250k rows, much larger than all of the tables combined. Clearly something is wierd.

I checked the mysql join docs for some help, and determined that the following provides the same results:

SELECT DISTINCT diameter
FROM inventory LEFT JOIN (wheel, wheel_fitment)
ON (wheel_fitment.wheel=wheel.id)
WHERE vehicle=4566

Only now the query takes less than .3 seconds, quite an improvement from 10 seconds! My guess is that MySQL is better able to optimize the latter query.

Viraj's Weblog

Donate to keep this site going!

Amount USD $

December 2005
Mon Tue Wed Thu Fri Sat Sun
<<  <   >  >>
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Search

Categories


Misc

Syndicate this blog XML

What is RSS?

powered by
b2evolution