【資料庫】之 MySQL效能分析
Explain
使用
EXPLAIN
關鍵字可以模擬優化器執行SQL
查詢語句,從而知道MySQL
是如何處理你的SQL
語句的。分 析你的查詢語句或是表結構的效能瓶頸。
準備
CREATE TABLE t1(id INT(10) AUTO_INCREMENT,content VARCHAR(100) NULL , PRIMARY KEY (id));
CREATE TABLE t2(id INT(10) AUTO_INCREMENT,content VARCHAR(100) NULL , PRIMARY KEY (id));
CREATE TABLE t3(id INT(10) AUTO_INCREMENT,content VARCHAR(100) NULL , PRIMARY KEY (id));
CREATE TABLE t4(id INT(10) AUTO_INCREMENT,content VARCHAR(100) NULL , PRIMARY KEY (id));
INSERT INTO t1(content) VALUES(CONCAT('t1_',FLOOR(1+RAND()*1000)));
INSERT INTO t2(content) VALUES(CONCAT('t2_',FLOOR(1+RAND()*1000)));
INSERT INTO t3(content) VALUES(CONCAT('t3_',FLOOR(1+RAND()*1000)));
INSERT INTO t4(content) VALUES(CONCAT('t4_',FLOOR(1+RAND()*1000)));
id 含義
select
查詢的序列號,包含一組數字,表示查詢中執行select
子句或操作表的順序。
①id 相同,執行順序由上至下
EXPLAIN SELECT * FROM t1, t2, t3 WHERE t1.id = t2.id AND t2.id = t3.id;
MySQL 5.5
MySQL 8.0
②id 不同,如果是子查詢,id 的序號會遞增,id 值越大優先順序越高,越先被執行
EXPLAIN SELECT t1.id FROM t1 WHERE t1.id IN (
SELECT t2.id FROM t2 WHERE t2.id IN (
SELECT t3.id FROM t3 WHERE t3.content = ''
)
);
MySQL 5.5
MySQL 8.0
③有相同也有不同
EXPLAIN SELECT t2.* FROM t2, (SELECT * FROM t3 WHERE t3.content='') s3 WHERE s3.id = t2.id;
MySQL 5.5
MySQL 8.0
id 如果相同,可以認為是一組,從上往下順序執行;在所有組中,id 值越大,優先順序越高,越先執行衍生 = DERIVED,關注點:id 號每個號碼,表示一趟獨立的查詢。一個 sql 的查詢趟數越少越好。
select_type含義
select_type
代表查詢的型別,主要是用於區別普通查詢、聯合查詢、子查詢等的複雜查詢。
屬性 | 含義 |
---|---|
SIMPLE | 簡單的 SELECT 查詢,查詢中不包含子查詢或者 UNION |
PRIMARY | 查詢中若包含任何複雜的子部分,最外層查詢則被標記為PRIMARY |
DERIVED | 在 FROM 列表中包含的子查詢被標記為 DERIVED,MySQL 會遞迴執行這些子查詢,把結果放在臨時表裡 |
SUBQUERY | 在 SELECT 或者 WHERE 列表中包含了子查詢 |
DEPEDENT SUBQUERY | 在 SELECT 或 WHERE 列表中包含了子查詢,子查詢基於外層 |
UNCACHEABLE SUBQUERY | 無法使用快取的子查詢 |
UNION | 若第二個SELECT出現在UNION之後,則被標記為UNION; 若UNION包含在FROM子句的子查詢中,外層SELECT將被標記為:DERIVED |
UNION RESULT | 從UNION表獲取結果的SELECT |
SIMPLE
EXPLAIN SELECT * FROM t1;
MySQL 5.5
MySQL 8.0
PRIMARY
查詢中若包含任何複雜的子部分,最外層查詢則被標記為
Primary
EXPLAIN SELECT * FROM (SELECT t1.content FROM t1) a;
MySQL 5.5
MySQL 8.0
DERIVED
在 FROM 列表中包含的子查詢被標記為 DERIVED(衍生),MySQL 會遞迴執行這些子查詢, 把結果放在臨時表裡。
SUBQUERY
在 SELECT 或 WHERE 列表中包含了子查詢。
EXPLAIN SELECT t2.id FROM t2 WHERE t2.id = (SELECT t3.id FROM t3 WHERE t3.id = 2);
MySQL 5.5
MySQL 8.0
DEPENDENT SUBQUERY
在 SELECT 或 WHERE 列表中包含了子查詢,子查詢基於外層。
EXPLAIN SELECT t2.id FROM t2 WHERE t2.id IN (SElECT t3.id FROM t3 WHERE t3.content='PfkHFe');
MySQL 5.5
MySQL 8.0
都是 where 後面的條件,
subquery
是單個值,dependent subquery
是一組值。
UNCACHEABLE SUBQUREY
當使用了@@來引用系統變數的時候,不會使用快取。
EXPLAIN SELECT * FROM t3 WHERE id = (SELECT id FROM t2 WHERE t2.id =@@sort_buffer_size);
MySQL 5.5
MySQL 8.0
UNION
若第二個
SELECT
出現在UNION
之後,則被標記為UNION
;若UNION
包含在FROM
子句的子查詢中,外層SELECT
將被標記為:DERIVED
。
EXPLAIN SELECT t2.id, t2.content FROM t2 UNION ALL SELECT t3.id, t3.content FROM t3;
MySQL 5.5
MySQL 8.0
UNION RESULT
從 UNION 表獲取結果的 SELECT。
type含義
type 是查詢的訪問型別。是較為重要的一個指標,結果值從最好到最壞依次是:
system
>const
>eq_ref
>ref
>fulltext
>ref_or_null
>index_merge
>unique_subquery
>index_subquery
>range
>index
>ALL
一般來說,得保證查詢至少達到
range
級別,最好能達到ref
。
system
表只有一行記錄(等於系統表),這是
const
型別的特列,平時不會出現,這個也可以忽略不計
const
表示通過索引一次就找到了,
const
用於比較primary key
或者unique
索引。因為只匹配一行資料,所以很快 如將主鍵置於where
列表中,MySQL
就能將該查詢轉換為一個常量。
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE t1.id = 1) s;
MySQL 5.5
MySQL 8.0
eq_ref
唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描。
EXPLAIN SELECT * FROM t1, t2 WHERE t1.id = t2.id;
MySQL 5.5
MySQL 8.0
ref
非唯一性索引掃描,返回匹配某個單獨值的所有行.本質上也是一種索引訪問,它返回所有匹配某個單獨值的行, 然而,它可能會找到多個符合條件的行,所以他應該屬於查詢和掃描的混合體。
沒用索引前:
EXPLAIN SELECT * FROM t1, t2 WHERE t1.content = t2.content;
MySQL 5.5
MySQL 8.0
建立索引後:
CREATE INDEX idx_ctnt on t2(content);
EXPLAIN SELECT * FROM t1, t2 WHERE t1.content = t2.content;
MySQL 5.5
MySQL 8.0
range
只檢索給定範圍的行,使用一個索引來選擇行。key 列顯示使用了哪個索引一般就是在你的 where 語句中出現 了 between、<、>、in 等的查詢這種範圍掃描索引掃描比全表掃描要好,因為它只需要開始於索引的某一點,而 結束語另一點,不用掃描全部索引。
EXPLAIN SELECT * FROM t1 WHERE t1.id<10;
MySQL 5.5
MySQL 8.0
EXPLAIN SELECT * FROM t1 WHERE t1.id IN(10, 13,33);
MySQL 5.5
MySQL 8.0
index
出現
index
是sql
使用了索引但是沒用通過索引進行過濾,一般是使用了覆蓋索引或者是利用索引進行了排序分組。
EXPLAIN SELECT * FROM t1;
MySQL 5.5
MySQL 8.0
EXPLAIN SELECT id FROM t1;
MySQL 5.5
MySQL 8.0
all
Full Table Scan
,將遍歷全表以找到匹配的行。
EXPLAIN SELECT * FROM t1, t2 WHERE t1.content = t2.content;
MySQL 5.5
MySQL 8.0
possible_keys 含義
顯示可能應用在這張表中的索引,一個或多個。查詢涉及到的欄位上若存在索引,則該索引將被列出,但不一 定被查詢實際使用。
key
實際使用的索引。如果為NULL,則沒有使用索引
key_len
表示索引中使用的位元組數,可通過該列計算查詢中使用的索引的長度。 key_len 欄位能夠幫你檢查是否充分的 利用上了索引。ken_len 越長,說明索引使用的越充分。
如何計算:
①先看索引上欄位的型別+長度比如 int=4 ; varchar(20) =20 ; char(20) =20
②如果是 varchar 或者 char 這種字串欄位,視字符集要乘不同的值,比如 utf-8 要乘 3,GBK 要乘 2,
③varchar 這種動態字串要加 2 個位元組
④允許為空的欄位要加 1 個位元組 第一組:key_len=age 的位元組長度+name 的位元組長度=4+1 + ( 20*3+2)=5+62=67 第二組:key_len=age 的位元組長度=4+1=5
ref
顯示索引的哪一列被使用了,如果可能的話,是一個常數。哪些列或常量被用於查詢索引列上的值。
rows
rows 列顯示 MySQL 認為它執行查詢時必須檢查的行數。越少越好!
Extra
其他的額外重要的資訊。
Using filesort
說明 mysql 會對資料使用一個外部的索引排序,而不是按照表內的索引順序進行讀取。MySQL 中無法利用索引 完成的排序操作稱為“檔案排序”。