MySQL 提供了一個 EXPLAIN 命令,它能夠對 SELECT 語句進行分析,並輸出 SELECT 執行的詳細信息,供開發人員有針對性的優化。算法
EXPLAIN SELECT * from USERS where id >1 ;
select_type
表示查詢的類型。經常使用的值以下:緩存
SIMPLE : 表示查詢語句不包含子查詢或union PRIMARY:表示此查詢是最外層的查詢 UNION:表示此查詢是UNION的第二個或後續的查詢 EXPLAIN SELECT * from user WHERE id < 3; DEPENDENT UNION:UNION中的第二個或後續的查詢語句,使用了外面查詢結果 UNION RESULT:UNION的結果 SUBQUERY:SELECT子查詢語句 DEPENDENT SUBQUERY:SELECT子查詢語句依賴外層查詢的結果。
type
表示存儲引擎查詢數據時採用的方式。比較重要的一個屬性,經過它能夠判斷出查詢是全表掃描仍是基於索引的部分掃描。經常使用屬性值以下,從上至下效率依次加強。函數
ALL:表示全表掃描,性能最差。 index:表示基於索引的全表掃描,先掃描索引再掃描全表數據。 range:表示使用索引範圍查詢。使用>、>=、<、<=、in等等。 ref:表示使用非惟一索引進行單值查詢。 eq_ref:通常狀況下出如今多表join查詢,表示前面表的每個記錄,都只能匹配後面表的一行結果。 const:表示使用主鍵或惟一索引作等值查詢,常量查詢。 NULL:表示不用訪問表,速度最快
possible_keys
表示查詢時可以使用到的索引。注意並不必定會真正使用,顯示的是索引名稱。性能
key
表示查詢時真正使用到的索引,顯示的是索引名稱。優化
rows
MySQL查詢優化器會根據統計信息,估算SQL要查詢到結果須要掃描多少行記錄。原則上rows是越少效率越高,能夠直觀的瞭解到SQL效率高低。spa
key_len
表示查詢使用了索引的字節數量。能夠判斷是否所有使用了組合索引。
key_len的計算規則以下:code
字符串類型 字符串長度跟字符集有關:latin1=一、gbk=二、utf8=三、utf8mb4=4 char(n):n*字符集長度 varchar(n):n * 字符集長度 + 2字節 數值類型 TINYINT:1個字節 SMALLINT:2個字節 MEDIUMINT:3個字節 INT、FLOAT:4個字節 BIGINT、DOUBLE:8個字節 時間類型 DATE:3個字節 TIMESTAMP:4個字節 DATETIME:8個字節 字段屬性 NULL屬性佔用1個字節,若是一個字段設置了NOT NULL,則沒有此項
Extra
Extra表示不少額外的信息,各類操做會在Extra提示相關信息,常見幾種以下:blog
Using where 表示查詢須要經過索引回表查詢數據。 Using index 表示查詢須要經過索引,索引就能夠知足所需數據。 Using filesort 表示查詢出來的結果須要額外排序,數據量小在內存,大的話在磁盤,所以有Using filesort建議優化。 Using temprorary 查詢使用到了臨時表,通常出現於去重、分組等操做。
InnoDB索引有聚簇索引(主鍵索引)和輔助索引。聚簇索引的葉子節點存儲行記錄,InnoDB必需要有,且只有一個。輔助索引的葉子節點存儲的是主鍵值和索引字段值,經過輔助索引沒法直接定位行記錄,一般狀況下,須要掃碼兩遍索引樹。
先經過輔助索引定位主鍵值,而後再經過聚簇索引定位行記錄,這就叫作回表查詢,它的性能比掃一遍索引樹低。排序
總結:經過索引查詢主鍵值,而後再去聚簇索引查詢記錄信息索引
即explain的輸出結果Extra字段爲Using index時,可以觸發索引覆蓋。
EXPLAIN SELECT e.* from EMPLOYEE e INNER JOIN COMPANY c on e.companyId = c.id
複合索引使用時遵循最左前綴原則,最左前綴顧名思義,就是最左優先,即查詢中使用到最左邊的列,那麼查詢就會使用到索引,若是從索引的第二列開始查找,索引將失效
CREATE TABLE `user2` ( `userid` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(20) NOT NULL DEFAULT '', `password` varchar(20) NOT NULL DEFAULT '', `usertype` varchar(20) NOT NULL DEFAULT '', PRIMARY KEY (`userid`), KEY `a_b_c_index` (`username`,`password`,`usertype`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
當存在username時會使用索引查詢:
explain select * from user2 where username = '1' and password = '1';
當沒有username時,不會使用索引查詢:
explain select * from user2 where password = '1';
MySQL在使用like模糊查詢時,索引能不能起做用?
MySQL在使用Like模糊查詢時,索引是能夠被使用的,只有把%字符寫在後面纔會使用到索引。
select * from user where name like '%o%'; //不起做用 select * from user where name like 'o%'; //起做用 select * from user where name like '%o'; //不起做用
若是MySQL表的某一列含有NULL值,那麼包含該列的索引是否有效?
對MySQL來講,NULL是一個特殊的值,從概念上講,NULL意味着「一個未知值」,它的處理方式與其餘值有些不一樣。
好比:不能使用=,<,>這樣的運算符,對NULL作算術運算的結果都是NULL,count時不會包括NULL行等,NULL比空字符串須要更多的存儲空間等
NULL列須要增長額外空間來記錄其值是否爲NULL。對於MyISAM表,每個空列額外佔用一位,四捨五入到最接近的字節。
雖然MySQL能夠在含有NULL的列上使用索引,但NULL和其餘數據仍是有區別的,不建議列上容許爲NULL。最好設置NOT NULL,並給一個默認值,好比0和 ‘’ 空字符串等,若是是datetime類型,也能夠設置系統當前時間或某個固定的特殊值,例如'1970-01-01 00:00:00'。
MySQL查詢支持filesort和index兩種方式的排序,filesort是先把結果查出,而後在緩存或磁盤進行排序操做,效率較低。使用index是指利用索引自動實現排序,不需另作排序操做,效率會比較高。
filesort有兩種排序算法:雙路排序和單路排序。
若是咱們Explain分析SQL,結果中Extra屬性顯示Using filesort,表示使用了filesort排序方式,須要優化。若是Extra屬性顯示Using index時,表示覆蓋索引,也表示全部操做在索引上完成,也可使用index排序方式,建議你們儘量採用覆蓋索引。
會使用index方式的排序
ORDER BY 子句索引列組合知足索引最左前列 explain select id from user order by id; //對應(id)、(id,name)索引有效 WHERE子句+ORDER BY子句索引列組合知足索引最左前列 explain select id from user where age=18 order by name; //對應 (age,name)索引
會使用filesort方式的排序
對索引列同時使用了ASC和DESC explain select id from user order by age asc,name desc; //對應 (age,name)索引 WHERE子句和ORDER BY子句知足最左前綴,但where子句使用了範圍查詢(例如>、<、in等) explain select id from user where age>10 order by name; //對應 (age,name)索引 ORDER BY或者WHERE+ORDER BY索引列沒有知足索引最左前列 explain select id from user order by name; //對應(age,name)索引 使用了不一樣的索引,MySQL每次只採用一個索引,ORDER BY涉及了兩個索引 explain select id from user order by name,age; //對應(name)、(age)兩個索引 WHERE子句與ORDER BY子句,使用了不一樣的索引 explain select id from user where name='tom' order by age; //對應 (name)、(age)索引 WHERE子句或者ORDER BY子句中索引列使用了表達式,包括函數表達式 explain select id from user order by abs(age); //對應(age)索引