1. SQL優化的步驟
- 發現有性能問題的SQL;
- 分析SQL執行計劃;
- 優化索引;
- 改寫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的語句。
- select_type:表示查詢類型
值 | 含義 |
---|---|
SIMPLE | 簡單查詢,不含有子查詢或者UNION操作的查詢 |
PRIMARY | 查詢中如果包含子查詢,那麼最外層的查詢則被標記位PRIMARY |
SUBQUERY | SELECT列表中的子查詢 |
DEPENDENT SUBQUERY | 被依賴的子查詢 |
-
table:表示執行結果的數據由哪個表輸出的
- <unionM,N>由id爲M,N查詢union產生的結果集; - <derived N>或<subquery N>由id爲N的查詢產生的結果集;
-
partitions:對於分區表,顯示查詢的分區id,對於非分區表,顯示爲null
-
type:查詢的方式
- ALL是全表掃描
- index表示全表索引掃描,遍歷的是索引樹
- range表示索引範圍掃描,常見於between > <等查詢條件
- eq_ref值唯一索引或主鍵查找,對於每一個索引,只有一條記錄與之匹配,常出現使用主鍵或唯一索引關聯join查詢中
- ref表示非唯一索引查找,返回匹配某個單獨值的所有行
- ref_or_null表示對於join查詢,附加了對NULL值列的查詢
- const表示表中有且只有一個匹配的行時,比如對主鍵或唯一索引的where查詢
-
possible_key:查詢中可能會用到的索引,比如:主鍵、唯一索引
-
key:查詢中實際使用到的索引
-
key_len:實際使用索引的長度
-
ref:如果查詢中未使用到任何索引,那麼ref列的值就爲null
-
rows:預估的掃描的行數
-
filtered:預估的符合條件的數據集在其所掃描的表的百分比,百分比越高,性能越好
-
extra:表示SQL用了哪些條件,比如using where、 distinct、not exists、using index(覆蓋索引:查詢的條件和結果完全不需要表掃描,都在索引上)、using temporary(使用臨時表)等等
4. SQL優化的手段
- 優化SQL查詢所涉及到的表中的索引
- 改寫SQL已達到更好的利用索引的目的
- 索引的作用:告訴存儲引擎如何快速找到數據
- 不同的存儲引擎的索引底層實現是不相同的
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;