天天看點

mysql主鍵跟索引的速度_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操作頻繁。