話說有這么一個表: CREATE TABLE `user_group` ( `id` int(11) NOT NULL auto_increment, `uid` int(11) NOT NULL, `group_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `uid` (`uid`), KEY `group_id` (`group_id`), ) ENGINE=InnoDB AUTO_INCREMENT=750366 DEFAULT CHARSET=utf8 看AUTO_INCREMENT就知道數(shù)據(jù)并不多,75萬條。然后是一條簡單的查詢: SELECT SQL_NO_CACHE uid FROM user_group WHERE group_id = 245; 很簡單對不對?怪異的地方在于:
如果只是就這么點差距其實不是什么大不了的事,但是真實的業(yè)務需求比這個復雜,造成的差距也很大:MyISAM只需要0.12s,InnoDB則需要2.2s.,最終定位到問題癥結(jié)是在這條SQL。 Explain的結(jié)果是: +----+-------------+------------+------+---------------+----------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+------+---------------+----------+---------+-------+------+-------+ | 1 | SIMPLE | user_group | ref | group_id | group_id | 4 | const | 5544 | | +----+-------------+------------+------+---------------+----------+---------+-------+------+-------+ 看起來已經(jīng)用上索引了,而這條SQL語句已經(jīng)簡單到讓我無法再優(yōu)化了。最后請前同事Gaston診斷了一下,他認為:數(shù)據(jù)分布上,group_id相同的比較多,uid散列的比較均勻,加索引的效果一般,但是還是建議我試著加了一個多列索引: ALTER TABLE user_group ADD INDEX group_id_uid (group_id, uid); 然后,不可思議的事情發(fā)生了……這句SQL查詢的性能發(fā)生了巨大的提升,居然已經(jīng)可以跑到0.00s左右了。經(jīng)過優(yōu)化的SQL再結(jié)合真實的業(yè)務需求,也從之前2.2s下降到0.05s。 再Explain一次: +----+-------------+------------+------+-----------------------+--------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+-----------------------+--------------+---------+-------+------+-------------+
| 1 | SIMPLE | user_group | ref | group_id,group_id_uid | group_id_uid | 4 | const | 5378 | Using index |
+----+-------------+------------+------+-----------------------+--------------+---------+-------+------+-------------+ 原來是這種叫覆蓋索引(covering index),MySQL只需要通過索引就可以返回查詢所需要的數(shù)據(jù),而不必在查到索引之后再去查詢數(shù)據(jù),所以那是相當?shù)目欤?!但是同時也要求所查詢的字段必須被索引所覆蓋到,在Explain的時候,輸出的Extra信息中如果有“Using Index”,就表示這條查詢使用了覆蓋索引。 |
|