1、在一個表執行了分別執行了兩條語句:
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秒
2、表結構以下,插入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的字段,並且在表中的數據都是填滿的。
3、首先咱們分析兩個語句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掃描表時按索引次序進行而不是行。它的主要優勢是避免了排序;最大的缺點是要承擔按索引次序讀取整個表的開銷。
4、分析:
1.因爲表的存儲引擎採用的InnoDB,InnoDB的索引屬於彙集索引,就是說表數據文件和索引文件都是同一個,表數據的分佈按照主鍵排序,以BTREE數據格式存儲,而輔助索引的葉子節點指向的是對應的主鍵。而上述表的REMARK和RESERVER的數據不少,致使硬盤存儲的數據塊不少,而主鍵索引的查找就會由於數據塊的增多,致使更多的IO操做,下降查詢效率。
而MyISAM引擎的索引屬於非彙集索引,索引文件跟數據文件是分開的。而索引文件的所指向的是對應數據的物理地址。
2.EXPLAIN 三個查詢的Extra都是「Using index」,表示這三個查詢的數據都是直接從索引獲取的,沒有經過主鍵,再獲取對應的一行數據,這就是索引覆蓋。
因此第一、3個查詢都是直接從輔助索引中查詢,而且獲取索引值返回,大大加快了效率,可是第三個查詢,MySQL會自動採用惟一鍵"UUID"做爲索引,這是爲何呢。而第二個遍歷的是主鍵索引,並且數據量大,IO操做頻繁。spa