1. 程式人生 > 其它 >MySQL --- 讀書筆記 --- EXPLAIN

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查詢都有一個這樣的屬性,表明它在整個大查詢裡面扮演的角色

    1. 查詢語句不包含UNION或者子查詢的都是SIMPLE型別
    2. 連線查詢也算是SIMPLE型別
    3. 包含UNION或者UNION ALL或者子查詢的大查詢,最左邊或者最外層的子查詢是PRIMARY型別
    4. 包含UNION或者UNION ALL的大查詢,除了最左邊的,其他的小查詢都是UNION型別
    5. 在包含UNION的大查詢,臨時表的型別是UNION RESULT
    6. 在包含子查詢中,並且是不相關子查詢,型別是SUBQUERY
    7. 在包含子查詢中,並且是相關子查詢,型別是DEPENDENT SUBQUERY
    8. 包含UNION或者UNION ALL的大查詢,小查詢依賴於外層查詢的話,除了最左的小查詢,其餘的型別是DEPENDENT UNION
    9. 包含派生表的大查詢,派生表對應的子查詢的型別是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:當不能有效使用到索引時,使用臨時表

小結

  • EXPLAIN不考慮各種cache
  • EXPLAIN不能顯示執行查詢所作的優化工作
  • EXPLAIN不會告訴你關於觸發器、儲存過程的資訊或使用者自定義函式對查詢的影響
  • 部分統計資訊是估算。不是精確

EXPLAIN的進一步使用

四種輸出格式
  1. 傳統格式
  2. JSON格式:FORMAT=JSON,JSON是輸出最詳盡的格式 ,裡面包含了執行的成本資訊
  3. 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_schemainformation_schema中的資料以更容易理解的方式總結歸納為檢視,目的是為了降低查詢performance_schema的複雜度

摘要






通過sys庫查詢時,會消耗大量資源收集相關資訊,嚴重的可能會導致業務請求被阻塞,建議不要生產頻繁地查詢sys