MySQL之SQL優化

1. SQL優化的步驟

  1. 發現有性能問題的SQL;
  2. 分析SQL執行計劃;
  3. 優化索引;
  4. 改寫SQL;

2. 發現有性能問題的SQL

  • 分析慢查詢日誌發現存在性能問題的SQL;

    • 配置慢查詢日誌:SET GLOBAL slow_query_log = ON

    • 指定慢查詢日誌位置:SET GOLBAL slow_query_log_file = /slow_query_log/slow_query_log.log

    • 設定最長查詢時間:SET GLOBAL long_query_time = x秒,如果等於0,則把所有SQL都寫入日誌中

    • 把沒有使用索引的SQL都記錄到日誌中:SET GLOBAL long_queries_not_using_indexes = ON

    • 常用的慢查詢日誌工具:

       1、mysqldumpslow:MySQL官方提供的慢查詢日誌分析工具,可以彙總除查詢條件外其他完全相同的SQL,並將分析結果按照參數中所指定的順序輸出。
       2、pt-query-digest:用於分析 MySQL 慢查詢的一個工具。
      
  • 數據庫實時監控長時間運行的SQL:獲取查詢時間超過0秒的SQL

    • SELECT * FROM information_schema.PROCESSLIST WHERE TIME >= 0;

3. 分析SQL執行計劃

  • 瞭解SQL如何訪問表中的數據;
  • 瞭解SQL如何使用表中的索引;
  • 瞭解SQL所使用的查詢類型;
  • 執行計劃內容分析:

id:查詢執行的順序,id相同時由上到下執行;id不同時,由大到小執行;

`EXPLAIN SELECT * FROM employee WHERE gender = '男'`

執行計劃如下:在這裏插入圖片描述

EXPLAIN SELECT * FROM USER u LEFT JOIN user_role ur ON u.id = ur.uid;

上面的SQL的執行計劃如下:
在這裏插入圖片描述
id相同的情況下,SQL由上至下開始執行,整個執行過程以u表爲基礎進行的;

EXPLAIN SELECT * FROM USER u WHERE u.id NOT IN (SELECT uid FROM user_role)

上面的SQL的執行計劃如下:
在這裏插入圖片描述
可以看出,id爲2的語句先執行,然後再執行id爲1的語句。

  1. select_type:表示查詢類型
含義
SIMPLE 簡單查詢,不含有子查詢或者UNION操作的查詢
PRIMARY 查詢中如果包含子查詢,那麼最外層的查詢則被標記位PRIMARY
SUBQUERY SELECT列表中的子查詢
DEPENDENT SUBQUERY 被依賴的子查詢
  1. table:表示執行結果的數據由哪個表輸出的

     -  <unionM,N>由id爲M,N查詢union產生的結果集;
     -  <derived N>或<subquery N>由id爲N的查詢產生的結果集;
    
  2. partitions:對於分區表,顯示查詢的分區id,對於非分區表,顯示爲null

  3. type:查詢的方式

    • ALL是全表掃描
    • index表示全表索引掃描,遍歷的是索引樹
    • range表示索引範圍掃描,常見於between > <等查詢條件
    • eq_ref值唯一索引或主鍵查找,對於每一個索引,只有一條記錄與之匹配,常出現使用主鍵或唯一索引關聯join查詢中
    • ref表示非唯一索引查找,返回匹配某個單獨值的所有行
    • ref_or_null表示對於join查詢,附加了對NULL值列的查詢
    • const表示表中有且只有一個匹配的行時,比如對主鍵或唯一索引的where查詢
  4. possible_key:查詢中可能會用到的索引,比如:主鍵、唯一索引

  5. key:查詢中實際使用到的索引

  6. key_len:實際使用索引的長度

  7. ref:如果查詢中未使用到任何索引,那麼ref列的值就爲null

  8. rows:預估的掃描的行數

  9. filtered:預估的符合條件的數據集在其所掃描的表的百分比,百分比越高,性能越好

  10. extra:表示SQL用了哪些條件,比如using where、 distinct、not exists、using index(覆蓋索引:查詢的條件和結果完全不需要表掃描,都在索引上)、using temporary(使用臨時表)等等

4. SQL優化的手段

  1. 優化SQL查詢所涉及到的表中的索引
  2. 改寫SQL已達到更好的利用索引的目的
  3. 索引的作用:告訴存儲引擎如何快速找到數據
  4. 不同的存儲引擎的索引底層實現是不相同的
    Innodb支持的索引類型:
  • Btree索引
  • 自適應hash索引
  • 全文索引
  • 空間索引

Btree索引的特點:

  • B+樹的結構來存儲索引數據
    -

  • B+樹是一個平衡二叉樹

  • 每一個葉子節點到根節點的距離是相同的

  • 每個葉子節點之間通過指針連接,方便快速查找

  • Btree索引適用於全值匹配的查詢

  • 適合處理範圍查找

  • 從索引的最左側開始匹配查找列

  • 應該在什麼列上建立索引:

    • where子句中的列;
    • 包含在order by、group by、distinct中的字段,索引列的順序和order by的順序一致;
    • 多表join的關聯列一定建立索引;
    • 儘量選擇篩選性較高的列;
  • 如何選擇複合索引的順序?

    • 區分度最高的列放在聯合索引的最左側;
    • 使用最頻繁的列放到聯合索引的最左側;
    • 儘量把字段長度小的列放在聯合索引列的最左側;
  • Btree索引的限制?

    • 只能從最左側開始按索引的順序使用索引,不能跳過索引;
    • 比如:聯合索引A、B、C,查詢的時候只用了A和C,跳過了B,這樣最後只能使用A;
    • NOT IN 和< >操作無法使用索引;
    • 索引列上不能使用表達式和函數;
  • 索引使用的誤區?

    • 索引越多越好,索引太多會降低插入和更新的效率;
    • 使用IN列表查詢不會用到索引,使用OR的確不會用到索引,使用IN會用到索引,但是IN中的數據不能太多;
    • 查詢過濾順序必須同索引鍵順序相同纔可以使用到索引,這是不對的,MySQL會自動調整索引順序,只要你再where表達式後面用到了索引;
  • SQL改寫的原則?

    • 使用outer in代替not in ;
    • 用計算列的方式巧妙的用到索引(MySQL5.7新增);
    • 拆分複雜的大SQL爲多個簡單的小SQL;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章