【深刻淺出mysql(第二版)18章學習筆記】
瞭解SQL的執行頻率以後,再繼續瞭解如何分析SQL語句。分析SQL語句能夠經過EXPLAIN、show profile、trace對SQL進行綜合分析,其中EXPLAIN比較經常使用。
mysql
Explain能夠定位SQL的執行問題,例如:
EXPLAIN SELECT sum(amount) from customer a, payment b WHERE 1=1 and a.customer_id = b.customer_id and email = 'JANE.BENNETT@sakilacutomer.org';
輸出結果:
sql
各個列名的含義:
select_type : 表示select的類型,常見取值以下:json
SIMPLE :簡單表,即不使用錶鏈接或子查詢;
PRIMARY: 主查詢,即外層查詢;
UNION : UNION 中的第二個或者後面的查詢語句;
SUBQUERY : 子查詢中的第一個select。性能
table:輸出結果集的表;
type : 表示Mysql在表中找到找到所需行的方式,或者叫訪問類型。常見類型以下:學習
ALL | index | range | ref | eq_ref | const/system | NULL
從左到右,性能由最差到最好。優化
possible_keys : 表示查詢時可能使用到的索引;
key : 表示實際使用的索引;
key_len : 使用到索引字段的長度;
ref :
rows: 掃描行的數量;
Extra: 執行狀況的說明和描述,包含不適合在其餘列中顯示可是對執行計劃很是重要的額外信息。
詳解 type 列:線程
全表掃描,mysql遍歷全表來找到匹配的行
EXPLAIN SELECT * FROM film WHERE rating > 9 ;
結果如圖:
3d
索引全掃描,mysql遍歷整個索引來查詢匹配的行
EXPLAIN SELECT title FROM film;
結果如圖:
code
索引範圍掃描,常見於** <、 <=、 >、 >= 、between**等操做符。
EXPLAIN SELECT * FROM payment WHERE customer_id > 300 AND customer_id <=350;
結果如圖:
orm
使用非惟一索引掃描或惟一索引的前綴掃描,返回匹配某個單獨值的記錄行
EXPLAIN SELECT * FROM payment WHERE customer_id =350;
結果如圖:
索引 idx_fk_customer_id 是非惟一索引。
與 ref 相似 ,區別在於使用的索引是惟一索引,對於每一個索引鍵值,表中只有一條記錄匹配。即在多表鏈接中使用 primary key或者 unique index 做爲關聯條件。
EXPLAIN SELECT * FROM film a, film_text b WHERE a.film_id = b.film_id;
結果如圖:
單表中最多有一個匹配行,查詢起來很是迅速,因此這個匹配行中的其餘列的值能夠被優化器在當前查詢中看成常量來處理。例如,根據主鍵 primary key 或者惟一索引 unique index 進行的查詢。
ALTER TABLE customer add UNIQUE INDEX uk_email (email); EXPLAIN SELECT * FROM (SELECT * FROM customer WHERE email = 'AARON.SELBY@sakilacustomer.org') a;
結果如圖:
經過惟一索引 uk_email 訪問的時候,類型 type=const;而僅有一條記錄的表中檢索時,類型 type = system。
mysql 不用訪問表或者索引,直接就能獲得結果。
EXPLAIN SELECT 1 FROM DUAL where 1;
結果如圖:
2)經過 show profile 分析SQL
【主要查看SQL語句執行的時候,時間耗費在什麼地方】
首先查詢當前mysql是否支持 profile (profile 能夠幫助瞭解SQL執行的過程)
SELECT @@have_profiling;
若是profiling是關閉的,能夠經過set語句在Session級別開啓profiling:
SELECT @@profiling; SET profiling=1;
關於profile的做用:
第一步:執行一個count(*)查詢
SELECT COUNT(*) FROM payment;
第二步:查看當前SQL的query id
show PROFILES;
第三步:經過 show profile for query 語句查看執行過程當中線程的每一個狀態和消耗的時間
show PROFILE for QUERY 167;
注:
[ ]Sending data 狀態表示mysql線程開始訪問數據並把結果返回給客戶端,而不單單是返回結果給客戶端。因爲在Sending data狀態下,mysql線程須要作大量的磁盤讀取操做,因此是整個查詢過程當中耗時最長的狀態。
[ ]show profile for query 語句也支持選擇all、 CPU、block io 、 context switch、page faults 等明細類型來查看mysql在使用什麼資源上耗費了太高的時間。例如,查看cpu的耗費時間:
首先打開trace ,設置格式爲JSON,設置trace最大可以使用的內存大小。
SET OPTIMIZER_TRACE="enabled=on",end_markers_in_json=on; SET optimizer_trace_max_mem_size=1000000;
執行示例:
SELECT rental_id FROM rental WHERE 1=1 and rental_date >= '2005-05-25 04:00:00' and rental_date <= '2005-05-25 05:00:00' and inventory_id=4466; // 如下語句會輸出一個格式爲json的跟蹤文件 SELECT * FROM information_schema.OPTIMIZER_TRACE;