一、EXPLAIN
做MySQL優化,我們要善用EXPLAIN查看SQL執行計劃。
下面來個簡單的示例,標註(1、2、3、4、5)我們要重點關注的數據
-
type列,連接類型。一個好的SQL語句至少要達到range級別。杜絕出現all級別。
-
key列,使用到的索引名。如果沒有選擇索引,值是NULL。可以採取強制索引方式
-
key_len列,索引長度。
-
rows列,掃描行數。該值是個預估值。
-
extra列,詳細說明。注意,常見的不太友好的值,如下:Using filesort,Using temporary。
-
MySQL中explain的type類型
| ALL | 全表掃描
| index | 索引全掃描
| range | 索引範圍掃描,常用語<,<=,>=,between等操作
| ref | 使用非唯一索引掃描或唯一索引前綴掃描,返回單條記錄,常出現在關聯查詢中
| eq_ref | 類似ref,區別在於使用的是唯一索引,使用主鍵的關聯查詢
| const/system | 單條記錄,系統會把匹配行中的其他列作爲常數處理,如主鍵或唯一索引查詢
| null | MySQL不訪問任何表或索引,直接返回結果
二、SQL 語句中 IN 包含的值不應過多
MySQL對於IN做了相應的優化,即將IN中的常量全部存儲在一個數組裏面,而且這個數組是排好序的。但是如果數值較多,產生的消耗也是比較大的。再例如:select id from t where num in(1,2,3) 對於連續的數值,能用between就不要用in了;再或者使用連接來替換。
三、SELECT語句務必指明字段名稱
SELECT*增加很多不必要的消耗(CPU、IO、內存、網絡帶寬);增加了使用覆蓋索引的可能性;當表結構發生改變時,前斷也需要更新。所以要求直接在select後面接上字段名。
四、當只需要一條數據的時候,使用limit 1
這是爲了使EXPLAIN中type列達到const類型
五、如果排序字段沒有用到索引,就儘量少排序
六、如果限制條件中其他字段沒有索引,儘量少用or
or兩邊的字段中,如果有一個不是索引字段,而其他條件也不是索引字段,會造成該查詢不走索引的情況。很多時候使用union all或者是union(必要的時候)的方式來代替“or”會得到更好的效果
八、不使用ORDER BY RAND()
select id from `dynamic` t1
join (select rand() * (select max(id) from `dynamic`) as nid) t2
on t1.id > t2.nid limit 1000;
select id from `dynamic` order by rand() limit 1000;
上面的SQL語句,可優化爲:
select id from `dynamic` t1
join (select rand() * (select max(id) from `dynamic`) as nid) t2
on t1.id > t2.nid limit 1000;
mysql explain 的詳細介紹還可以參考下面的網址