MySQL索引實驗-主鍵索引一定比輔助索引快嗎?【轉載】

一、在一個表執行了分別執行了兩條語句:
a.SELECT ID FROM MNG_ROLE ORDER BY ID; -- 耗時37秒
b.SELECT ID FROM MNG_ROLE ORDER BY ID, NAME; -- 耗時0.01秒
c.SELECT ID FROM MNG_ROLE; -- 耗時0.22秒
二、表結構如下,插入3萬條數據,而且REMARK和RESERVER字段都是填滿數據:
====================================================
CREATE TABLE `MNG_ROLE` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`NAME` varchar(50) NOT NULL,
`CREATE_DATE` char(8) NOT NULL,
`CREATE_TIME` char(6) DEFAULT NULL,
`UUID` char(32) NOT NULL,
`REMARK` varchar(3000) NOT NULL DEFAULT ‘‘,
`RESERVER` varchar(3000) NOT NULL DEFAULT ‘RESERVER‘,
PRIMARY KEY (`ID`),
UNIQUE KEY `UK_UUID` (`UUID`) USING BTREE,
KEY `INDEX_NAME_CREATE_DATE_TIME_REMARK` (`NAME`,`CREATE_DATE`,`CREATE_TIME`,`REMARK`(255)) USING BTREE,
KEY `ID_NAME` (`ID`,`NAME`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=300001 DEFAULT CHARSET=utf8
====================================================
這個表建立了一個主鍵索引(ID),唯一鍵約束(UUID),普通索引(INDEX_NAME_CREATE_DATE_TIME_REMARK、ID_NAME)而且需要注意的是,這裏有兩個字符數爲3000的字段,而且在表中的數據都是填滿的。
三、首先我們分析兩個語句EXPLAIN的結果:
MariaDB [yjtmng]> EXPLAIN SELECT ID FROM MNG_ROLE ORDER BY ID;
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | MNG_ROLE | index | NULL | PRIMARY | 4 | NULL | 145134 | Using index |
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
1 row in set (0.00 sec)
MariaDB [yjtmng]> EXPLAIN SELECT ID FROM MNG_ROLE ORDER BY ID, NAME;
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | MNG_ROLE | index | NULL | ID_NAME | 156 | NULL | 145134 | Using index |
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
1 row in set (0.00 sec)
MariaDB [yjtmng]> explain SELECT ID FROM MNG_ROLE;
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | MNG_ROLE | index | NULL | UK_UUID | 96 | NULL | 145134 | Using index |
+------+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
1 row in set (0.00 sec)
上面兩個查詢,前者是用到了主鍵索引,後兩者用到了輔助索引,但是爲什麼用到主鍵索引會更慢呢?上述三個查詢的type=index,這個方式跟全表掃描一樣,只是MySQL掃描表時按索引次序進行而不是行。它的主要優點是避免了排序;最大的缺點是要承擔按索引次序讀取整個表的開銷。
四、分析:
1.由於表的存儲引擎採用的InnoDB,InnoDB的索引屬於聚集索引,就是說表數據文件和索引文件都是同一個,表數據的分佈按照主鍵排序,以BTREE數據格式存儲,而輔助索引的葉子節點指向的是對應的主鍵。而上述表的REMARK和RESERVER的數據很多,導致硬盤存儲的數據塊很多,而主鍵索引的查找就會因爲數據塊的增多,導致更多的IO操作,降低查詢效率。
而MyISAM引擎的索引屬於非聚集索引,索引文件跟數據文件是分開的。而索引文件的所指向的是對應數據的物理地址。
2.EXPLAIN 三個查詢的Extra都是“Using index”,表示這三個查詢的數據都是直接從索引獲取的,沒有通過主鍵,再獲取對應的一行數據,這就是索引覆蓋。
所以第1、3個查詢都是直接從輔助索引中查詢,並且獲取索引值返回,大大加快了效率,但是第三個查詢,MySQL會自動採用唯一鍵"UUID"作爲索引,這是爲什麼呢。而第二個遍歷的是主鍵索引,而且數據量大,IO操作頻繁。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章