EXPLAIN執行計划分類
案例表結構:
索引結構:
1.all 全表掃描
MYSQL掃描全表來找到匹配的行
例如:
EXPLAIN SELECT * FROM `t_user` WHERE nick_name='鵝鵝鵝'
例如
EXPLAIN SELECT nn_number FROM `t_user` WHERE nick_name='鵝鵝鵝'
2.index 索引全掃描
索引全掃描,MYSQL遍歷整個索引來查找匹配的行。(雖然where條件中沒有用到索引,但是要取出的列nn_number是索引包含的列,所以只要全表掃描索引即可,直接使用索引樹查找數據)
例如:
EXPLAIN SELECT nn_number FROM `t_user`
3.range 索引范圍掃描
索引范圍掃描,常見於<、<=、>、>=、between等操作符(因為nn_number是索引,所以只要查找索引的某個范圍即可,通過索引找到具體的數據)
例如:nn_number 為 普通索引時
EXPLAIN SELECT * FROM `t_user` WHERE nn_number between 200000 and 800000
例如: user_id 是唯一索引時
EXPLAIN SELECT * FROM `t_user` WHERE user_id between 200000 and 800000
注意:
range類型: 在查詢數據量不同的情況下,不一定走索引,MySQL 優化器會可能會優化成全表掃描 type為all
例如:數據量較小的情況下 ,可以看到是可以走索引的
EXPLAIN SELECT * FROM `t_user` WHERE nn_number > 1000 and nn_number < 145000
例如:數據量較大的情況下,SQL不會走索引
EXPLAIN SELECT * FROM `t_user` WHERE nn_number > 1000 and nn_number < 145000000
原因:
MySQL 索引不總是會起作用,MySQL 優化器會判斷SQL是否走索引查的更快,若是,就走索引
數據量超過30%是優化器判斷是否走索引的一個標准,還有其他標准,
參考MySQL 文檔: https://dev.mysql.com/doc/refman/5.7/en/range-optimization.html
Each table index is queried, and the best index is used unless the optimizer believes that it is more efficient to use a table scan.
表中的每個索引都會被訪問,當中最佳的那個則會被使用,除非優化器認為使用全表查詢比使用所有查詢更高效。
At one time, a scan was used based on whether the best index spanned more than 30% of the table, but a fixed percentage no longer determines the choice between using an index or a scan.
曾經,是否進行全表掃描取決於使用最好的索引查出來的數據是否超過表的30%的數據,但是現在這個固定百分比(30%)不再決定使用索引還是全表掃描了。
The optimizer now is more complex and bases its estimate on additional factors such as table size, number of rows, and I/O block size.
優化器現在變得更復雜,它考慮的因素更多,比如表大小、行數量、IO塊大小。
可以使用強制SQL走索引,改變MySQL 優化器對SQL 的優化
例如:
EXPLAIN SELECT * FROM `t_user` force INDEX(idx_user_nn_number) WHERE nn_number > 1000 and nn_number < 145000000
4.ref
使用非唯一性索引或者唯一索引的前綴掃描,返回匹配某個單獨值的記錄行。
EXPLAIN SELECT * FROM `t_user` WHERE nn_number ='10086'
5.eq_ref
相對於ref來說就是使用的是唯一索引,對於每個索引鍵值,只有唯一的一條匹配記錄(在聯表查詢中使用primary key或者unique key作為關聯條件)
6.const / system
單表中最多只有一條匹配行,查詢起來非常迅速,所以這個匹配行中的其他列中的值可以被優化器在當前查詢中當做常量來處理。例如根據主鍵或者唯一索引進行的查詢。
EXPLAIN SELECT * FROM `t_user` WHERE user_id=146484531
7.null
MYSQL不用訪問表或者索引就直接能到結果。dual是一個虛擬的表,可以直接忽略
EXPLAIN select 1 from dual
MYSQL不用訪問表或者索引就直接能到結果。