1. 程式人生 > 其它 >MySQL之SQL分析工具使用

MySQL之SQL分析工具使用

概述:MySQL有三種SQL分析工具,分別為explain、profiling、optimizer_trace,下面分別介紹一下怎麼使用的

  1. 環境

    1. MySQL 5.7

    2. 測試表,隨便找個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='反饋表'
      
  2. 分析

    1. explain 一般用來分析 查詢語句

      1. 使用:

        explain SELECT * FROM  config where id = 1;
        
      2. 結果:

      3. 各欄位含義:參考 MYSQL explain詳解

        1. id 是select 查詢序列號,,查詢序列號即為sql語句執行的順序

        2. select_type 是指 select 型別,有以下幾種取值

          1. simple 簡單的select 沒有union和子查詢

          2. primary 在有子查詢的語句中,最外面的select 查詢就是primary

          3. union語句的第二個或者說是後面那一個

          4. DEPENDENT UNION(UNION中的第二個或後面的SELECT語句,依賴於外面的查詢)

          5. UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

          6. SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

          7. DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

          8. DERIVED(派生表的SELECT, FROM子句的子查詢)

          9. UNCACHEABLE SUBQUERY(一個子查詢的結果不能被快取,必須重新評估外連結的第一行)

        3. table輸出的行所用的表

        4. type 連線型別,下面從最佳型別到最差型別介紹

          1. system表示僅有一行,這是const型別的特例,一般不會出現

          2. const 表示 只比較primary key或者unique索引且表最多有一行匹配

          3. eq_ref 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連線中使用primary key或者 unique key作為關聯條件

          4. ref 表示上述表的連線匹配條件,即哪些列或常量被用於查詢索引列上的值

          5. range 只檢索給定範圍的行,使用一個索引來選擇行

          6. index Full Index Scan,index與ALL區別為index型別只遍歷索引樹

          7. ALL Full Table Scan, MySQL將遍歷全表以找到匹配的行

        5. possible_keys

          指出MySQL能使用哪個索引在表中找到記錄,查詢涉及到的欄位上若存在索引,則該索引將被列出,但不一定被查詢使用(該查詢可以利用的索引,如果沒有任何索引顯示 null)

        6. key

          key列顯示MySQL實際決定使用的鍵(索引),必然包含在possible_keys中

          如果沒有選擇索引,鍵是NULL。要想強制MySQL使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。

        7. key_len

          key_len顯示的值為索引欄位的最大可能長度,即key_len是根據表定義計算而得,不是通過表內檢索出的

        8. ref

          列與索引的比較,表示上述表的連線匹配條件,即哪些列或常量被用於查詢索引列上的值

        9. rows

          估算出結果集行數

        10. Extra

          1. Using where:不用讀取表中所有資訊,僅通過索引就可以獲取所需資料
          2. Using temporary:表示MySQL需要使用臨時表來儲存結果集,常見於排序和分組查詢,常見 group by ; order by
          3. Using filesort:當Query中包含 order by 操作,而且無法利用索引完成的排序操作稱為“檔案排序”
          4. Using join buffer:該值強調了在獲取連線條件時沒有使用索引,並且需要連線緩衝區來儲存中間結果。
          5. Impossible where:這個值強調了where語句會導致沒有符合條件的行(通過收集統計資訊不可能存在結果)。
          6. Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函式結果中返回一行
          7. No tables used:Query語句中使用from dual 或不含任何from子句,關於 dual可以參考:mysql中dual表
      4. 注:

        1. EXPLAIN沒有關於觸發器、儲存過程的資訊或使用者自定義函式對查詢的影響情況
        2. EXPLAIN不考慮各種Cache
        3. EXPLAIN不能顯示MySQL在執行查詢時所作的優化工作
        4. 部分統計資訊是估算的,並非精確值
    2. profiling 一般用來分析 查詢語句

      1. 使用

        // 開啟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;
        
    3. optimizer_trace

      1. 支援操作

        SELECT、INSERT、REPLACE、UPDATE、DELETE、EXPLAIN、SET、DECLARE、CASE、IF、RETURN、CALL

      2. 使用

        // 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的內容進行分析
        
      3. 結果分析:

        {
            "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詳解

注:

  1. 本文參考:MYSQL explain詳解mysql optimizertrace_MySQL 調優 | OPTIMIZER_TRACE詳解
  2. 如需轉載請註明出處:https://www.cnblogs.com/zhuchenglin/p/15099036.html