Linux下MySQL性能的检查和调优方法(二)

2014-11-24 17:38:35 · 作者: · 浏览: 2
cks desc limit 10;


+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+


| id | select_type | table | type | possible_keys | key| key_len | ref | rows | Extra |


+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+


|1 | SIMPLE| imgs| ref| userid| userid | 51| const | 2944 | Using where; Using filesort |


+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+


1 row in set (0.00 sec)


这个结果和userid="7mini"的结果基本相同,但是mysql用userid索引一次搜索后结果集的大小达到2944条,这2944条记录都会加入内存进行filesort,效率比起7mini那次来说就差很多了。这时可以有两种办法可以解决,第一种办法是再加一个索引和判断条件,因为我只需要根据点击量取最大的10条数据,所以有很多数据我根本不需要加进来排序,比如点击量小于10的,这些数据可能占了很大部分。


我对clicks加一个索引,然后加入一个where条件再查询:


create index clicks on imgs(clicks);


mysql> desc select * from imgs where userid="admin" order by clicks desc limit 10;


+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+


| id | select_type | table | type | possible_keys | key| key_len | ref | rows | Extra |


+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+


|1 | SIMPLE| imgs| ref| userid,clicks | userid | 51| const | 2944 | Using where; Using filesort |


+----+-------------+-------+------+---------------+--------+---------+-------+------+-----------------------------+


1 row in set (0.00 sec)


这时可以看到possible_keys变成了userid,clicks,possible_keys是可以匹配的所有索引,mysql会从possible_keys中自己判断并取用其中一个索引来执行语句,值得注意的是,mysql取用的这个索引未必是最优化的。这次查询mysql还是使用userid这个索引来查询的,并没有按照我的意愿,所以结果还是没有什么变化。改一下sql加上use index强制mysql使用clicks索引:


mysql> desc select * from imgs use index (clicks) where userid='admin' and clicks>10 order by clicks desc limit 10


+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+


| id | select_type | table | type| possible_keys | key| key_len | ref| rows | Extra |


+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+


|1 | SIMPLE| imgs| range | clicks| clicks | 4 | NULL | 5455 | Using where |


+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+


1 row in set (0.00 sec)


这时mysql用到了clicks索引进行查询,但是结果集比userid还要大!看来还要再进行限制:


mysql> desc select * from imgs use index (clicks) where userid='admin' and clicks>1000 order by clicks desc limit 10


+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+


| id | select_type | table | type| possible_keys | key| key_len | ref| rows | Extra |


+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+


|1 | SIMPLE| imgs| range | clicks| clicks | 4 | NULL |312 | Using where |


+----+-------------+-------+-------+---------------+--------+---------+------+------+-------------+


1 row in set (0.00 sec)


加到1000的时候结果集变成了312条,排序效率应该是可以接受。


不过,采用换索引这种优化方式需要取一个采样点,比如这个例子中的1000这个数字,这样,对userid的每个数值,都要去找一个采样点,这样对程序来说是很难办的。如果按1000取样的话,那么userid='7mini'这个例子中,取到的结果将不会是8条,而是2条,给用户造成了困惑。


当然还有另一种办法,加入双索引:


create index userid_clicks on imgs (userid, clicks)


mysql> desc select * from imgs where userid="admin" order by clicks desc limit 10;


+