慢查詢及其優化處理方法
慢查詢定義
mysql慢查詢日誌是mysql提供的一種日誌記錄,它是用來記錄在mysql中相應時間超過閾值的語句,就是指執行時間超過long_query_time值的sql,會被記錄在慢查詢日誌中。long_query_time的預設值是10,意思是執行10S之上的語句
慢查詢設定
-
查詢慢sql時間設設定的值
show variables like 'long%'; -
修改慢查詢時間閾值
set global long_query_time=4 -
展示慢sql的開啟狀態和日誌檔案的存放位置
show variables like 'slow%';
slow_launch_time 2
slow_query_log ON
slow_query_log_file /root/mysql/datas/mysql/slow_query.log -
未使用索引的查詢被記錄到慢查詢日誌中。如果調優的話,建議開啟這個選項。如果開啟了這個引數,full index scan的sql也會被記錄到慢查詢日誌中。
show variables like 'log_queries_not_using_indexes';
開啟開關
set global log_queries_not_using_indexes=1 -
查詢有多少條慢查詢記錄
show global status like '%Slow_queries%';
通過explain來分析SQL效能(Mysql)
1. 什麼是explain
explain是MySql中用來分析SQL語句執行效率的一條命令,通過explain命令我們可以知道以下資訊:表的讀取順序,資料讀取操作的型別,哪些索引可以使用,哪些索引實際使用了,表之間的引用,每張表有多少行被優化器查詢等資訊。
2. explain 引數解析
【id】
select查詢的序列號包含一組數字,表示查詢中執行select子句或者操作表的順序
id相同,執行順序由上至下
id不同,如果是子查詢,id的序號會遞增,id值越大優先順序越高,越先執行
id有相同的也有不同的,則相同的看為一組再繼續按照上面兩條規則執行
【select_type】
SIMPLE:簡單的select查詢,查詢中不包含子查詢或者UNION
PRIMARY:查詢中若包含任何複雜的子部分,最外層查詢則被標記為
SUBQUER: 在select或者where列表中包含了子查詢
DERIVED:在from列表中包含的子查詢被標記為DERIVED(衍生)MySql會遞迴執行這些子查詢,把結果放在臨時表
UNION:若第二個select出現在union之後,則被標記為UNION,若union包含在from子句的子查詢中,外層select被標記為:DERIVED
UNION RESULT:從union表獲取結果的select
【type】
- all:全表掃描
- index:全索引掃描
- range:範圍掃描
- ref:不唯一的索引掃描,有多個符合條件的行
- eq_ref:唯一的索引掃描,只有一條記錄與之匹配,常見於主鍵索引
- const、system:這兩種的情況都比較好,前一種值的是條件為常量
- null:執行階段不需要訪問的表
索引type從優到差:System-->const-->eq_ref-->ref-->ref_or_null-->index_merge-->unique_subquery-->index_subquery-->range-->index-->all.
【table】
- 對應的表
【possible_keys】
- 哪些索引可能有助於查詢。如果為空,說明沒有可用的索引
【key】
- 實際從 possible_key 選擇使用的索引,如果為 NULL,則沒有使用索引。很少的情況 下,MYSQL 會選擇優化不足的索引。這種情 況下,可以在 SELECT語句中使用 USE INDEX (indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制 MYSQL 忽略索引
【key_len】
- 使用的索引的長度。在不損失精確性的情況 下,長度越短越好。
【ref】 - 這一列顯示了哪些欄位或者常量被用來和key配合從表中查詢記錄出來
【rows】 - 估計要讀取的行數
【extra】 - Using index:使用覆蓋索引,表示查詢索引就可查到所需資料,不用掃描表資料檔案,往往說明效能不錯。
- Using Where:在儲存引擎檢索行後再進行過濾,使用了where從句來限制哪些行將與下一張表匹配或者是返回給使用者。
- Using temporary:在查詢結果排序時會使用一個臨時表,一般出現於排序、分組和多表 join 的情況,查詢效率不高,建議優化。
- Using filesort:對結果使用一個外部索引排序,而不是按索引次序從表裡讀取行,一般有出現該值,都建議優化去掉,因為這樣的查詢
CPU 資源消耗大。
優化方式
1. SQL調優
- 避免 SELECT *,只查詢需要的欄位。
- 小表驅動大表,即小的資料集驅動大的資料集: 當B表的資料集比A表小時,用in優化 exist兩表執行順序是先查B表再查A表查詢語句:SELECT * FROM tb_dept WHERE id in (SELECT id
FROM tb_dept) ; 當A表的資料集比B表小時,用exist優化in ,兩表執行順序是先查A表,再查B表,查詢語句:SELECT * FROM A WHERE EXISTS (SELECT id FROM B WHERE A.id = B.ID) ;- 儘量使用連線代替子查詢,因為使用 join 時,MySQL 不會在記憶體中建立臨時表。
2. 優化索引的使用
- 儘量使用主鍵查詢,而非其他索引,因為主鍵查詢不會觸發回表查詢。
- 不做列運算,把計算都放入各個業務系統實現
- 查詢語句儘可能簡單,大語句拆小語句,減少鎖時間
- or 查詢改寫成 union 查詢
- 不用函式和觸發器
- 避免 %xx 查詢,可以使用:select * from t where reverse(f) like reverse('%abc');
- 少用 join 查詢
- 使用同類型比較,比如 '123' 和 '123'、123 和 123
- 儘量避免在 where 子句中使用 != 或者 <> 操作符,查詢引用會放棄索引而進行全表掃描
- 列表資料使用分頁查詢,每頁資料量不要太大
- 避免在索引列上使用 is null 和 is not null
3. 表結構設計優化
- 使用可以存下資料最小的資料型別。
- 儘量使用 tinyint、smallint、mediumint 作為整數型別而非 int。
- 儘可能使用 not null 定義欄位,因為 null 佔用 4 位元組空間。數字可以預設 0 ,字串預設 “”
- 儘量少用 text 型別,非用不可時最好獨立出一張表。
- 儘量使用 timestamp,而非 datetime。
- 單表不要有太多欄位,建議在 20 個欄位以內。
- Mysql常用資料型別儲存大小及範圍:https://blog.csdn.net/HXNLYW/article/details/100104768
4. show profiles 分析sql 效能
1. show profiles功能介紹
show profile是由Jeremy Cole捐獻給MySQL社群版本的。預設的是關閉的,但是會話級別可以開啟這個功能。開啟它可以讓MySQL收集在執行語句的時候所使用的資源
2. 檢視並開啟功能
為了統計報表,把profiling設為1
Profiling 功能由MySQL會話變數 : profiling控制,預設是OFF.關閉狀態。select @@profiling; 或者show variables like '%profi%';
mysql> select @@profiling;
+-------------+
| @@profiling |
+-------------+
| 0 |
+-------------+
mysql> set profiling = 1;
Query OK, 0 rows affected, 1 warning (0.00 sec)
3. 使用方法
執行一個sql語句
SELECT passrate FROM user_center
使用
SHOW PROFILES;
show profile for QUERY [QUERYID]
來檢視sql執行的詳情資訊
profiling_history_size 控制,預設15條
set profiling_history_size =100; 修改條數顯示