MySQL語句定位性能問題-explain

1.執行計劃

語法:explain select....
在這裏插入圖片描述
使用extended可以在原來查詢計劃上提供一些優化的信息
語法:explain extended select ....,然後通過show warnings來查看相應的優化信息
在這裏插入圖片描述
,測試時發現一個警告,含義EXTENDED將被移除[本地環境mysql5.7]
嘗試不使用EXTENDED參數,執行show warning明顯,發現確實是可以使用的並消除了這個警告
在這裏插入圖片描述

2. 執行計劃包含的信息

雖然不同版本的存儲引擎執行計劃不完全相同,但基本信息一致

          id: 1
 select_type: SIMPLE
       table: student
  partitions: NULL
        type: ALL
ossible_keys: NULL
         key: NULL
     key_len: NULL
         ref: NULL
        rows: 2
    filtered: 100.00
       Extra: NULL

下面進行解釋:
id:由一組數字組成,表示子查詢執行的順序。id相同執行順序自上而下

 explain SELECT
	i.cust_id AS '客戶ID',
	i.cust_name AS '客戶姓名',
	IF (l.cust_lmt < '1000',1000,  l.cust_lmt) AS '額度'
FROM
	cust_inf i
	JOIN cust_lmt l ON i.cust_id = l.cust_id ;

在這裏插入圖片描述
id不同,id越大優先級越高,越先被執行

explain	SELECT * FROM student union SELECT * FROM student ;

在這裏插入圖片描述
id爲null時表示是一個結果集,不需要使用他查詢,常出現包含union等查詢語句中
select_type
每個子查詢的查詢類型,常見如下表

select_type description
SIMPLE 不包含任何子查詢或union等查詢
PRIMARY 包含子查詢,最外層查詢顯示爲PRIMARY
SUBQUERY 在select或where子句中
DERIVED from字句中包含的查詢
UNION 出現在union後的查詢語句中
UNION RESULT 從UNION中獲取結果集

table
查詢涉及到的數據表
如果查詢使用別名,就顯示別名,如果不涉及對數據表的操作,顯示爲null,如果是尖括號括起來的就標識這個是臨時表,後邊的N就是執行計劃中的id,表示結果
來自於這個查詢產生。如果是尖括號括來<union M,N>,與類似,也是一個臨時表,標識這個結果來自於union查詢的id爲M,N的結果集。
type
訪問類型:

  • ALL 掃描全表數據
  • index 遍歷索引
  • range 索引範圍內查找
  • index_subquery在子查詢中使用ref
  • unique_subquery在子查詢中使用eq_ref
  • ref_or_null 對Null進行優化的ref
  • fulltext 使用全文索引
  • ref 使用非唯一索引查找數據
  • eq_ref 在join查詢中使用PRIMARY KEY or UNIQUE NOT NULL索引關聯
  • const使用主鍵或者唯一索引,且匹配結果只有一條記錄
  • system const鏈接類型的特例,查詢的表爲系統表

在這裏插入圖片描述
性能從好到差依次爲:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,除了ALL之外,其他type類型都可以使用到索引,除了index_merge之外,其他的type類型只可以用到一個索引。
所以通過執行查詢計劃查下某張表的查詢type爲ALL,可以考慮添加索引,或者更換查詢方式,使用索引進行查詢。

possible_keys
可能使用的索引,注意不一定會使用。查詢涉及到的字段上若存在索引,則該索引將被列出來,當該列爲NULL時就要考慮當前SQL是否需要優化了。

key
顯示MySQL在查詢中使用的索引,若沒有引用索引,顯示爲NULL
提示:查詢中若使用了覆蓋索引(覆蓋索引:索引的數據覆蓋了需要查詢的所有數據),則該列僅出現在key列表中

select_type爲index_merge時,這裏可能出現兩個以上的索引,其他的select_type這裏只會出現一個。

key_length
索引長度char()、varchar()索引長度的計算公式

(Character Set:utf8mb4=4,utf8=3,gbk=2,latin1=1) * 列長度 + 1(允許null) + 2(變長列)

其他類型索引長度的計算公式:

CREATE TABLE `student` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(128) NOT NULL DEFAULT '',
 `age` int(11),
 PRIMARY KEY (`id`),
 UNIQUE KEY `idx` (`name`),
 KEY `idx_age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

name索引長度爲:編碼爲utf8mb4,列長爲128,不允許爲NULL,字段類型爲varchar(128)。key_length=128*4+0+2=514;
在這裏插入圖片描述
同理,age索引長度:int類型佔4位,允許爲null,索引長度爲5。
在這裏插入圖片描述
ref
表示上述表的連接匹配條件,即那些類或常量被用於查找索引列的值

如果是使用常數等值查詢,這裏會顯示const,如果是連接查詢,被驅動表的執行計劃這類會顯示驅動表的關聯字段,如果是條件使用了表達式或者函數,或者條件列發生了內部隱式轉換,這裏可能顯示爲func

rows
返回估算的結果集數目,注意這並不是一個準確值。

extra
extra的信息非常豐富,常見的有:
Using index使用覆蓋索引
Using where使用了where子句過濾結果集
Using filesort使用文件排序,使用非索引列進行排序時出現,非常消耗性能,儘量優化。
Using temporary使用了臨時表

3.一些優化建議

1.SQL語句不要寫的太複雜,儘量簡單,不要嵌套太多層
2.使用“臨時表”緩存查詢結果
3.使用like要注意是否會導致全表掃描
例如:SELECT * FROM table where username like ‘%peiqi%’;
關鍵詞前面有%會導致全表掃描
4.儘量避免使用!=或<>操作符
where語句中使用!=或者<>,引擎將放棄使用索引進而全表掃描
5.儘量避免使用or來連接查詢條件
在where子句中使用or來連接查詢條件,引擎將放棄索引進而全表掃描
可以使用
select id from t where num=‘10’
union all
select id from t where num=‘20’
替代
select id from t where num=‘10’ or num =‘20’

6.儘量避免使用in和not in
在where子句中使用in和not in,搜索引擎可能會放棄索引而進行全表掃描
可以使用
select id from t where num between 10 and 20;
替換
select id from where num in (10,20);
7. 可以考慮強制查詢使用索引
select * from table force index(PRI) limit 2;(強制使用主鍵)
select* from table force index(hollis_index) limit 2;(強制使用索引hollis_index)
select * from table force index(PRI,hollis_index) limit 2;(強制使用索引PRI和hollis_index)
8.儘量避免使用表達式、函數等操作作爲查詢條件
9.儘量避免大事務操作,提高系統併發能力
10.儘量避免使用遊標
11.任何地方都不要使用select* from t,使用具體字段替代*,不返回任何用不到的字段
12.,儘可能使用varchar和nvarchar替代char和nchar
13.儘量使用數字型字段,如果只含數字信息的字段被設計成字符型,鄭輝降低查詢和連接的性能,並且會增加存儲開銷。
14.索引並不是越多越好,索引可以提高select的查詢效率,但是同時也會降低insert和select的效率
15.並不是所有的索引都有效,SQL是根據表中的數據來進行查詢優化的,當索引列有大量的重複時,SQl查詢可能不會使用索引.

參考

文章內容來源

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章