MySQL --- 讀書筆記 --- EXPLAIN
-
last_query_cost
,查詢使用的頁數量,衡量執行計劃的成本
定位執行慢的SQL:慢查詢日誌
-
慢查詢日誌,用於記錄執行過程中,響應時間超過閾值的語句,具體指執行時間超過
long_query_time
值的SQL,預設值是10s
-
預設系統是沒有開啟慢查詢日誌的,因為開啟之後會帶來一定的效能影響
-
檢視慢查詢是否開啟
show variables like '%slow_query_log'
- 開啟慢查詢
set global slow_query_log='ON'
- 檢視閾值
show variables like '%long_query_time%'
- 設定閾值
set global long_query_time=1
- 檢視系統中有多少條慢查詢記錄
show global status like '%slow_queries%'
慢查詢日誌分析工具:mysqldumpslow
檢視SQL執行成本:show profile
分析查詢語句:EXPLAIN
定位到查詢慢的語句之後,我們就可以使用EXPLAIN
工具做針對性的分析,通過這個工具我們可以知道
- 表的讀取順尋
- 資料讀取操作的操作型別
- 哪些索引可以使用
- 哪些索引被實際使用
- 表之間的引用
- 每張表有多少行被優化器查詢
工具分析後的顯示是一個執行計劃,它們有很多引數
-
table:工具查詢後的每一條記錄都對應著一個表
-
id:在一個大的查詢語句中,一個
SELECT
關鍵字對應一個唯一的id;id相同,執行順序從上到下,id不同,值越大優先順序越高,一個不同的id代表一趟獨立的查詢 -
select_type:每一個select查詢都有一個這樣的屬性,表明它在整個大查詢裡面扮演的角色
- 查詢語句不包含
UNION
或者子查詢的都是SIMPLE
型別 - 連線查詢也算是
SIMPLE
型別 - 包含
UNION
或者UNION ALL
或者子查詢的大查詢,最左邊或者最外層的子查詢是PRIMARY
型別 - 包含
UNION
或者UNION ALL
的大查詢,除了最左邊的,其他的小查詢都是UNION
型別 - 在包含
UNION
的大查詢,臨時表的型別是UNION RESULT
- 在包含子查詢中,並且是不相關子查詢,型別是
SUBQUERY
- 在包含子查詢中,並且是相關子查詢,型別是
DEPENDENT SUBQUERY
- 包含
UNION
或者UNION ALL
的大查詢,小查詢依賴於外層查詢的話,除了最左的小查詢,其餘的型別是DEPENDENT UNION
- 包含派生表的大查詢,派生表對應的子查詢的型別是
DERIVED
- 查詢語句不包含
-
type:執行計劃的一條記錄就代表著對某個表的執行查詢時的訪問方法,
type
就表明這個訪問方法是什麼,完整的訪問方法有如下幾種,效能從高到低排列-
system:當表中只有一條記錄,並且儲存引擎的統計資料是精確的,比如,MyISAM、Memory
-
const:當根據主鍵或者唯一索引列與常數做等值匹配
-
eq_ref:在連線查詢中,如果被驅動表是通過主鍵或者唯一索引列等值匹配的方式,那麼對被驅動表的訪問是
eq_ref
-
ref:當通過普通的二級索引列與常量做等值匹配
-
fulltext
-
ref_or_null:當對普通二級索引做等值匹配時,該索引列的值可以是
NULL
SELECT * FROM s1 WHERE k1='a' OR k1 IS NULL
-
index_merge:單表訪問在某些場景下可以使用索引合併的方式查詢
SELECT * FROM s1 WHERE k1='a' OR k2='b' // k1和k2都有索引
-
unique_subquery:針對一些包含
IN
子查詢的語句中,當查詢優化器決定將IN
子查詢優化為EXISTS
子查詢,而且子查詢可以使用到主鍵等值匹配的時候 -
index_subquery
-
range:使用索引獲取某些範圍的記錄
-
index:當可以使用
索引覆蓋
,但需要掃描全部索引記錄時 -
ALL:全表掃描
-
-
possible_keys和key:可能用到的索引和實際會用到的索引
-
key_len:實際使用到的索引長度(bytes),值越大越好,主要針對聯合索引,有一定參考意義
-
ref:當使用索引列等值匹配時,與索引列進行等值匹配的物件資訊;比如只是一個常數或者某個列
-
rows:預估需要讀取的記錄條數,值越小越好
-
filtered:某個表經過搜尋條件過濾之後剩餘記錄條數的百分比;對於單表查詢來說,這個值意義不大,主要是在連線查詢中,驅動表對應的執行計劃的該值,它決定了被驅動表需要執行的次數(rows * filtered)
-
Extra:用來說明一些額外資訊,可以根據這個值更準確的理解MySQL到底如何執行給定的查詢語句,有幾個最重要的資訊如下
- No tables used:當查詢語句中沒有
FROM
關鍵字時 - Impossible WHERE:
WHERE
關鍵字的條件永遠是FALSE
- Using where:全表掃描時,使用
WHERE
;或者有索引但不是全部條件都包含索引列的時候 - No matching row:當查詢列表處使用聚合函式,但是
WHERE
條件沒有符合的記錄 - Using index:當可以使用
覆蓋索引
的時候,不需要回表操作時 - Using index condition:搜尋條件中雖然出現了索引列,但卻不能使用到索引;出現
索引條件下推
- Using join buffer:連線查詢中,當被驅動表不能使用索引時,MySQL會分配一塊記憶體來加快查詢速度,也就是
基於塊的巢狀迴圈演算法
- No exists:在左外連線時,
WHERE
條件要求被驅動表某個列是NULL,但是這個列不可能是NULL時出現 - Using intersect(..)/union(..)/sort_union(..):索引合併
- Zero limit:
LIMIT
限制是0 - Using filesort:排序操作無法使用到索引時
- Using temporary:當不能有效使用到索引時,使用臨時表
- No tables used:當查詢語句中沒有
小結
- EXPLAIN不考慮各種cache
- EXPLAIN不能顯示執行查詢所作的優化工作
- EXPLAIN不會告訴你關於觸發器、儲存過程的資訊或使用者自定義函式對查詢的影響
- 部分統計資訊是估算。不是精確
EXPLAIN的進一步使用
四種輸出格式
- 傳統格式
- JSON格式:
FORMAT=JSON
,JSON是輸出最詳盡的格式 ,裡面包含了執行的成本資訊 - TREE格式:主要根據查詢的各個部分之間的關係和各部分的執行順序
分析優化器執行計劃:trace
OPTIMIZER_TRACE
可以跟蹤優化器做出的各種決策,並將跟蹤結果記錄到INFORMATION_SCHEMA.OPTIMZER_TRACE
- 預設關閉,需要開啟
SET optimizer_trace="enabled=on", end_markers_in_json=on;
set optimizer_trace_max_mem_size=100000;
MySQL監控分析分析檢視:sys-schema
它將performance_schema和information_schema中的資料以更容易理解的方式總結歸納為檢視,目的是為了降低查詢performance_schema的複雜度
摘要
通過sys庫查詢時,會消耗大量資源收集相關資訊,嚴重的可能會導致業務請求被阻塞,建議不要生產頻繁地查詢sys