1. 程式人生 > 其它 >【資料庫】之 MySQL效能分析

【資料庫】之 MySQL效能分析

技術標籤:MySQL學習筆記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

出現indexsql使用了索引但是沒用通過索引進行過濾,一般是使用了覆蓋索引或者是利用索引進行了排序分組。

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 中無法利用索引 完成的排序操作稱為“檔案排序”。