MySQL SQL優化 - 覆蓋索引(covering index)
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就知道數據并不多,75萬條。簡單的查詢:
SELECT SQL_NO_CACHE uid FROM user_group WHERE group_id = 245;
-- SQL_NO_CACHE 不使用緩存提示
Explain的結果是:
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+
| 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 | |
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+
看起來已經用上索引了,數據分布上,group_id相同的比較多,uid散列的比較均勻,加索引的效果一般,試著加了一個多列索引:
ALTER TABLE user_group ADD INDEX group_id_uid (group_id, uid);
這句SQL查詢的性能發生了巨大的提升,居然已經可以跑到0.00s左右了。經過優化的SQL再結合真實的業務需求,也從之前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只需要通過索引就可以返回查詢所需要的數據,而不必在查到索引之后再去查詢數據,所以相當快!!但是同時也要求所查詢的字段必須被索引所覆蓋到,在Explain的時候,輸出的Extra信息中如果有“Using Index”,就表示這條查詢使用了覆蓋索引。