MySQL SQL最佳化 - 覆蓋索引(covering index)

jichengjie發表於2018-04-21
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”,就表示這條查詢使用了覆蓋索引。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26870952/viewspace-2153164/,如需轉載,請註明出處,否則將追究法律責任。

相關文章