MySQL之SQL分析工具使用
概述:MySQL有三種SQL分析工具,分別為explain、profiling、optimizer_trace,下面分別介紹一下怎麼使用的
-
環境
-
MySQL 5.7
-
測試表,隨便找個MySQL的表都可以,例:
CREATE TABLE `config` ( `id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT, `key` varchar(255) NOT NULL DEFAULT '' COMMENT '配置key,唯一', `value` text NOT NULL COMMENT '反饋內容', `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0 線下,1 線上', `prefix` varchar(50) NOT NULL DEFAULT '' COMMENT '配置字首,建議和專案名稱有關', `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '建立時間', `update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新時間', PRIMARY KEY (`id`), UNIQUE KEY `type_prefix_key` (`type`,`prefix`,`key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='反饋表'
-
-
分析
-
explain 一般用來分析 查詢語句
-
使用:
explain SELECT * FROM config where id = 1;
-
結果:
-
各欄位含義:參考 MYSQL explain詳解
-
id 是select 查詢序列號,,查詢序列號即為sql語句執行的順序
-
select_type 是指 select 型別,有以下幾種取值
-
simple 簡單的select 沒有union和子查詢
-
primary 在有子查詢的語句中,最外面的select 查詢就是primary
-
union語句的第二個或者說是後面那一個
-
DEPENDENT UNION(UNION中的第二個或後面的SELECT語句,依賴於外面的查詢)
-
UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)
-
SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)
-
DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)
-
DERIVED(派生表的SELECT, FROM子句的子查詢)
-
UNCACHEABLE SUBQUERY(一個子查詢的結果不能被快取,必須重新評估外連結的第一行)
-
-
table輸出的行所用的表
-
type 連線型別,下面從最佳型別到最差型別介紹
-
system表示僅有一行,這是const型別的特例,一般不會出現
-
const 表示 只比較primary key或者unique索引且表最多有一行匹配
-
eq_ref 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連線中使用primary key或者 unique key作為關聯條件
-
ref 表示上述表的連線匹配條件,即哪些列或常量被用於查詢索引列上的值
-
range 只檢索給定範圍的行,使用一個索引來選擇行
-
index Full Index Scan,index與ALL區別為index型別只遍歷索引樹
-
ALL Full Table Scan, MySQL將遍歷全表以找到匹配的行
-
-
possible_keys
指出MySQL能使用哪個索引在表中找到記錄,查詢涉及到的欄位上若存在索引,則該索引將被列出,但不一定被查詢使用(該查詢可以利用的索引,如果沒有任何索引顯示 null)
-
key
key列顯示MySQL實際決定使用的鍵(索引),必然包含在possible_keys中
如果沒有選擇索引,鍵是NULL。要想強制MySQL使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。
-
key_len
key_len顯示的值為索引欄位的最大可能長度,即key_len是根據表定義計算而得,不是通過表內檢索出的
-
ref
列與索引的比較,表示上述表的連線匹配條件,即哪些列或常量被用於查詢索引列上的值
-
rows
估算出結果集行數
-
Extra
- Using where:不用讀取表中所有資訊,僅通過索引就可以獲取所需資料
- Using temporary:表示MySQL需要使用臨時表來儲存結果集,常見於排序和分組查詢,常見 group by ; order by
- Using filesort:當Query中包含 order by 操作,而且無法利用索引完成的排序操作稱為“檔案排序”
- Using join buffer:該值強調了在獲取連線條件時沒有使用索引,並且需要連線緩衝區來儲存中間結果。
- Impossible where:這個值強調了where語句會導致沒有符合條件的行(通過收集統計資訊不可能存在結果)。
- Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函式結果中返回一行
- No tables used:Query語句中使用from dual 或不含任何from子句,關於 dual可以參考:mysql中dual表
-
-
注:
- EXPLAIN沒有關於觸發器、儲存過程的資訊或使用者自定義函式對查詢的影響情況
- EXPLAIN不考慮各種Cache
- EXPLAIN不能顯示MySQL在執行查詢時所作的優化工作
- 部分統計資訊是估算的,並非精確值
-
-
profiling 一般用來分析 查詢語句
-
使用
// 開啟profiling set profiling=1; // 執行要分析的查詢語句 SELECT * FROM config where id = 1; // 獲取系統中儲存的所有 Query 的 profile 概要資訊 show profiles; // 查詢資源消耗情況 Duration:SQL語句執行時長 Block_ops_in和Block_ops_out表示塊儲存裝置輸入和輸出的次數,即從硬碟讀取和寫入資料的次數 show profile for query queryid; show profile cpu, block, io for query queryid; // 關閉profiling SET profiling = 0;
-
-
optimizer_trace
-
支援操作
SELECT、INSERT、REPLACE、UPDATE、DELETE、EXPLAIN、SET、DECLARE、CASE、IF、RETURN、CALL
-
使用
// enabled:optimizer_trace、one_line:是否開啟單行儲存。 set optimizer_trace="enabled=on,one_line=off"; // 檢視optimizer_trace配置 show variables like '%optimizer_trace%'; //預設情況下,由於optimizer_trace_offset=-1,optimizer_trace_limit=1,記錄最近的一條SQL語句,展示時,每次展示1條資料; // 如果改成 SET optimizer_trace_offset=-2, optimizer_trace_limit=1 ,則會記錄倒數第二條SQL語句; //Maximum allowed cumulated size of stored optimizer traces 單位位元組 SET OPTIMIZER_TRACE_MAX_MEM_SIZE=1000000 // 查詢結果 select * from information_schema.optimizer_trace; //OPTIMIZER_TRACE結果分析 //QUERY:查詢語句 //TRACE:QUERY欄位對應語句的跟蹤資訊 //MISSING_BYTES_BEYOND_MAX_MEM_SIZE:跟蹤資訊過長時,被截斷的跟蹤資訊的位元組數。 //INSUFFICIENT_PRIVILEGES:執行跟蹤語句的使用者是否有檢視物件的許可權。當不具有許可權時,該列資訊為1且TRACE欄位為空,一般在呼叫帶有SQL SECURITY DEFINER的檢視或者是儲存過程的情況下,會出現此問題。 // 主要對trace的內容進行分析
-
結果分析:
{ "steps": [ { "join_preparation": { "select#": 1, "steps": [ { // 格式化SQL "expanded_query": "/* select#1 */ select `config`.`id` AS `id`,`config`.`key` AS `key`,`config`.`value` AS `value`,`config`.`type` AS `type`,`config`.`prefix` AS `prefix`,`config`.`create_time` AS `create_time`,`config`.`update_time` AS `update_time` from `config` where (`config`.`id` = 1) limit 0,5000" } ] } }, { // 優化階段的執行過程 "join_optimization": { "select#": 1, "steps": [ { // 對條件處理,主要對WHERE條件進行優化處理 "condition_processing": { // 優化物件型別。WHERE條件句或者是HAVING條件句 "condition": "WHERE", // 優化前的原始語句 "original_condition": "(`config`.`id` = 1)", "steps": [ { // 轉換型別句 "transformation": "equality_propagation", //轉換之後的結果輸出 "resulting_condition": "multiple equal(1, `config`.`id`)" }, { "transformation": "constant_propagation", "resulting_condition": "multiple equal(1, `config`.`id`)" }, { "transformation": "trivial_condition_removal", "resulting_condition": "multiple equal(1, `config`.`id`)" } ] } }, { // 用於替換虛擬生成列 "substitute_generated_columns": {} }, { //分析表之間的依賴關係 "table_dependencies": [ { // 涉及的表名 "table": "`config`", //行是否可能為NULL,這裡是指JOIN操作之後,這張表裡的資料是不是可能為NULL。如果語句中使用了LEFT JOIN,則後一張表的row_may_be_null會顯示為true "row_may_be_null": false, //表的對映編號,從0開始遞增 "map_bit": 0, //依賴的對映表。主要是當使用STRAIGHT_JOIN強行控制連線順序或者LEFT JOIN/RIGHT JOIN有順序差別時,會在depends_on_map_bits中展示前置表的map_bit值 "depends_on_map_bits": [] } ] }, { //列出所有可用的ref型別的索引。如果使用了組合索引的多個部分,則會在ref_optimizer_key_uses下列出多個元素,每個元素中會列出ref使用的索引及對應值。 "ref_optimizer_key_uses": [ { "table": "`config`", "field": "id", "equals": "1", "null_rejecting": false } ] }, { //用於估算需要掃描的記錄數。 "rows_estimation": [ { "table": "`config`", "rows": 1, "cost": 1, "table_type": "const", "empty": false } ] }, { "condition_on_constant_tables": "1", "condition_value": true }, { "attaching_conditions_to_tables": { "original_condition": "1", "attached_conditions_computation": [], "attached_conditions_summary": [] } }, { //改善執行計劃 "refine_plan": [] } ] } }, { // 執行階段的執行過程 "join_execution": { "select#": 1, "steps": [] } } ] }
注:本文所舉例子過於簡單,有些情況沒有覆蓋到,更詳細的對trace的內容分析,可參考用MySQL的optimizer_trace進行sql調優、mysql optimizertrace_MySQL 調優 | OPTIMIZER_TRACE詳解
-
-
注: