[TOC]
最後修改時間: 2019年10月21日15:08:59
救急
show full processlist
查看當前線程處理情況, 確認當前有哪些語句在執行, 執行情況如何.
特別注意執行時間長的, 如果確定有問題, 那麼可以使用 kill {id}
幹掉該連接
show full processlist
等價於以下語句
select id, db, user, host, command, time, state, info
from information_schema.processlist
order by time desc;
注意:
-
show processlist
時, root賬號可以看到所有賬號的連接, 如果是普通賬號則只能看到自己的連接. - 如果顯示長度太長看的很亂, 可以使用
\G
, 即show full processlist\G
, 來將顯示結果縱向輸出, 方便查看.
擴展.
\g
等價於分號
\G
是將顯示的表格以縱向輸出, 方便查看.
Slow Query Log 慢查詢日誌
慢查詢日誌用於記錄執行時間超過指定閥值的SQL命令.
確認開啓情況
mysql> show variables like 'slow_query_log%';
+---------------------+------------------------------------------------+
| Variable_name | Value |
+---------------------+------------------------------------------------+
| slow_query_log | ON |
| slow_query_log_file | C:\laragon\data\mysql\DESKTOP-C1GGBS1-slow.log |
+---------------------+------------------------------------------------+
mysql> show variables like 'long_query_time';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 1.000000 |
+-----------------+----------+
開啓方式
配置文件
############### 慢查詢日誌 ################
# 打開慢查詢日誌
slow_query_log=1
# 日誌記錄位置
log_output=file
# 慢查詢日誌記錄文件
slow_query_log_file=/var/run/mysqld/mysqld-slow.log
# 慢查詢時間閥值
long_query_time=10
命令方式(mysqld實例重啓後失效)
-- 必須全局開啓慢查詢日誌記錄
set global slow_query_log=1;
-- 設置慢查詢時間閥值
set global long_query_time=1;
如果想要分析一些語句的執行, 則可以考慮將當前Session的慢查詢時間閥值設爲0
set long_query_time=0;
注意
當數據庫被拖垮時(高負載), 任何簡單的語句都可能執行超時, 此時的慢查詢日誌能提供的幫助就有限了.
慢查詢日誌分析工具
mysqldumpslow
在實際生產環境中,如果要手工分析日誌,查找、分析SQL,顯然是個體力活,MySQL提供了日誌分析工具mysqldumpslow
# 分析慢日誌
mysqldumpslow -a -n 50 -s c /var/run/mysqld/mysqld-slow.log
# 參數說明
--verbose 版本
--debug 調試
--help 幫助
-v 版本
-d 調試模式
-s ORDER 排序方式, 默認是 'at'
what to sort by (al, at, ar, c, l, r, t), 'at' is default
al: average lock time 平均鎖定時間
ar: average rows sent 平均返回記錄數
at: average query time 平均查詢時間
c: count 訪問計數
l: lock time 鎖定時間
r: rows sent 返回記錄
t: query time 查詢時間
-r 反轉順序,默認文件倒序拍。reverse the sort order (largest last instead of first)
-t NUM 顯示前N條
-a 不要將SQL中數字轉換成N,字符串轉換成S。don't abstract all numbers to N and strings to 'S'
-n NUM abstract numbers with at least n digits within names
-g PATTERN 正則匹配;grep: only consider stmts that include this string
-h HOSTNAME mysql機器名或者IP;hostname of db server for *-slow.log filename (can be wildcard),
default is '*', i.e. match all
-i NAME name of server instance (if using mysql.server startup script)
-l 總時間中不減去鎖定時間;don't subtract lock time from total time
示例
得到返回記錄集最多的10個SQL。
mysqldumpslow -s r -t 10 /database/mysql/mysql06_slow.log
得到訪問次數最多的10個SQL
mysqldumpslow -s c -t 10 /database/mysql/mysql06_slow.log
得到按照時間排序的前10條裏面含有左連接的查詢語句。
mysqldumpslow -s t -t 10 -g “left join” /database/mysql/mysql06_slow.log
另外建議在使用這些命令時結合 | 和more 使用 ,否則有可能出現刷屏的情況。
mysqldumpslow -s r -t 20 /mysqldata/mysql/mysql06-slow.log | more
SQL Explain
對於慢查詢日誌中執行慢的語句分析其 SQL語句的執行計劃
EXPLAIN 可以幫助瞭解:
- 數據表的讀取順序
- SELECT子句的類型
- 數據表的訪問類型
- 可使用的索引 possible_keys
- 實際使用的索引 key
- 使用的索引長度 ken_len
- 上一個表的連接匹配條件
- 被優化器查詢的行的數量
- 額外的信息(如使用使用外部排序, 是否使用臨時表)
舉例
EXPLAIN 結果列分析
<u>字段 id</u>
SQL 執行順序是根據
- id從大到小執行
- id相同時按照順序從上往下執行.
<u>字段 select_type(查詢類型)</u>
查詢類型 | 說明 |
---|---|
SIMPLE | 簡單查詢 不包含UNION查詢或子查詢 |
PRIMARY | 最外層查詢 查詢中若 包含任何複雜的子部分,最外層查詢則被標記爲PRIMARY |
SUBQUERY | 子查詢 在 SELECT 或 WHERE 中包含了子查詢 |
DEPENDENT SUBQUERY | !!! 子查詢, 但依賴於外層查詢的結果 注意確認, 避免大表驅動小表 |
DERIVED | 子查詢 在 FROM 列表中包含的子查詢被標記爲 DERIVED(衍生) |
UNION | 聯合 UNION 若第二個SELECT出現在UNION之後,則被標記爲UNION |
UNION RESULT | 使用聯合的結果 從UNION表獲取結果的SELECT |
關於UNION, 網上有寫以下這段, 但我個人不理解UNION 若第二個SELECT出現在UNION之後,則被標記爲UNION:若UNION包含在FROM子句的子查詢中,外層SELECT將被標記爲:DERIVED
<u>字段 table(數據表)</u>
訪問的數據表
<u>字段 partitions(分區)</u>
匹配的分區
<u>字段 type(訪問方式)</u>
查詢時的訪問方式, 性能:all < index < range < index_merge < ref < eq_ref < system/const
一般來說至少需要保證訪問方式是 range, 最好是 ref 級別.
訪問方式 | 說明 |
---|---|
ALL | 全表掃描,對於數據表從頭到尾找一遍select * from tb1; 特別的:如果有limit限制,則找到之後就不在繼續向下掃描 select * from tb1 where email = '[email protected]' select * from tb1 where email = '[email protected]' limit 1; 雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個後就不再繼續掃描。 |
INDEX | 全索引掃描,對索引從頭到尾找一遍 因爲非主鍵索引樹比較小, 所以會比 ALL 更快 |
RANGE | 對索引列進行範圍查找 通常是在索引樹上快速定位到某一索引項, 再向左/右遍歷. |
INDEX_MERGE | 合併索引,使用多個單列索引搜索, 最後結果取交集或並集 比如使用了UNION 且單獨用到了兩個索引. |
REF | 使用索引快速定位(根據索引查找一個或多個值), 該索引是 普通索引 或 唯一索引的部分前綴 |
EQ_REF | 使用主鍵索引或唯一索引快速定位 通常出現在多表的join查詢, 連接時使用primary key 或 unique 索引(都只能匹配到一行記錄) |
CONST | 通過主鍵或唯一索引精確查找到一行 常量 表最多有一個匹配行(主鍵或唯一索引),因爲僅有一行,在這行的列值可被優化器剩餘部分認爲是常數,const表很快,因爲它們只讀取一次 |
SYSTEM | 系統 表僅有一行, 這是const聯接類型的一個特例, 可以忽略這種情況。 |
Q. ALL 和 INDEX 的區別
A. 兩個都是全索引掃描, 不同的是 ALL 是對主鍵索引掃描, INDEX 是對非主鍵索引掃描.
這裏要理解, 所謂的全表掃描指的是對主鍵索引掃描.
Q. EQ_REF
和 CONST
的區別
A. 相同點都是使用主鍵/唯一索引精確查找到行記錄. 不同點在於:
-
CONST
查詢條件通常是索引列 = 具體常量值
-
EQ_REF
通常是在多表關聯查詢時作爲連接條件使用.
<u>字段 possible_keys(候選索引)</u>
<u>字段 key(實際使用的索引)</u>
如果是合併索引(INDEX_MERGE), 則此處可能存在超過1個的key
<u>字段 key_len(使用索引的實際長度)</u>
該字段可以評估組合索引是否完全被使用或僅僅是最左前綴被用到.
該字段顯示的值爲索引字段的最大可能長度, 並非實際使用長度.(即 key_len 是根據表定義計算, 而非表內檢索)
計算規則
字段類型 | 計算方式 | |
---|---|---|
字符串 | char(n) | n字節長度 |
varchar(n) | 若是utf8編碼, 則是 n3 + 2 字節 如果是 utf8mb4 編碼, 則是 4 n + 2 字節. |
|
數值 | tinyint | 1字節 |
smallint | 2字節 | |
mediumint | 3字節 | |
int | 4字節 | |
bigint | 8字節 | |
時間 | date | 3字節 |
timestamp | 4字節 | |
datetime | 8字節 |
如果對應索引字段允許爲 null, 則還要額外消耗1個字節來存儲 NULL.
<u>字段 ref</u>
表示索引的查找條件, 可能是常量(const) 或 聯合查詢中另一張表的某個字段.
<u>字段 row(掃描行數)</u>
估算的需要掃描的行數, 注意是估算的.
在某些情況下若索引統計信息偏差較大, 則此處的預估掃描行數也會過大, 導致影響查詢計劃的選擇.
可以使用 SHOW INDEX FROM 表名
來查看索引統計信息
可以使用 ANYLYSIS TABLE 表名
來重新統計索引信息.
<u>字段 filtered</u>
<u>字段 Extra(額外信息)</u>
該列包含MySQL解決查詢的詳細信息
值 | 說明 |
---|---|
Using filesort | mysql無法依靠索引直接獲取有序記錄, 而是對結果進行額外排序. mysql有兩種文件排序算法,這兩種排序方式都可以在內存或者磁盤上完成 explain不會告訴你mysql將使用哪一種文件排序 也不會告訴你排序會在內存裏還是磁盤上完成。 |
Using index | 使用覆蓋索引,以避免訪問表。不要把覆蓋索引和index訪問類型弄混了。 |
Using index condition | 索引下推優化, 5.6新增特性 |
Using temporary | 意味着mysql在對查詢結果排序時會使用一個臨時表 |
Using where | 使用了 where 過濾 這意味着mysql服務器將在存儲引擎檢索行後再進行過濾 許多where條件裏涉及索引中的列,當(並且如果)它讀取索引時,就能被存儲引擎檢驗 因此不是所有帶where子句的查詢都會顯示“Using where”。 有時“Using where”的出現就是一個暗示:查詢可受益於不同的索引。 |
Range checked for each record(index map: N) | 這個意味着沒有好用的索引,新的索引將在聯接的每一行上重新估算,N是顯示在possible_keys列中索引的位圖,並且是冗餘的。 |
using join buffer | 在表聯結時, 使用了連接緩存 |
Profiling
寫在最前: SHOW PROFILE 命令將被棄用, 注意, 僅僅是
SHOW PROFILE
命令棄用.替代方案是從 information_schema 中的profiling數據表進行查看, 可參數鏈接:
SHOW PROFILE 命令方式(舊)
查看語句執行的時間在各個步驟的開銷
show profile 分析SQL性能工具(檢測數據存在於臨時表中)
- 在會話級別開啓profile
SET profiling=1;
- 發送sql
-
查看profile的資源開銷結果
-
show profiles
查看所有的分析結果(會有一個數量上限) -
show profile
查看最後一條執行語句的分析結果 -
show profile for query <id>
查看指定執行語句的詳細分析結果 -
show profile cpu, block io for query <id>
查看詳細信息, 且包含 cpu, block.io 執行時間
-
- 關閉profile
這一部分更詳細的可以參考如:
information_schema .profiling
待用到時補充.