主要思路
實時分析(show full processlist;)結合延後分析(mysql.slow_log),對sql語句進行優化
實時分析
檢視有哪些執行緒正在執行
2show processlist;
show full processlist;
-- 按照客戶端ip對當前連線使用者進行分組
select substring_index(host,':',1) as h,count(host) as c,user from information_schema.processlist group by h order by c desc,user;
-- 按使用者名稱對當前連線使用者進行分組
select substring_index(host,':',1) as h,count(host) as c,user from information_schema.processlist group by user order by c desc,user;
各種耗時sql對應的特徵改表copying to tmp table記憶體不夠用,轉成磁碟copying to tmp table on disk傳輸資料量大reading from net
sending data沒有索引copying to tmp table
sorting result
creating sort index
sorting result
延後分析
設定慢查詢引數
4slow_query_log 1
log_queries_not_using_indexes off
long_query_time 5
slow_query_log 1# 建資料庫
create table `slow_log_2019-05-30` (
`start_time` timestamp(6) not null default current_timestamp(6) on update current_timestamp(6),
`user_host` mediumtext not null,
`query_time` time(6) not null,
`lock_time` time(6) not null,
`rows_sent` int(11) not null,
`rows_examined` int(11) not null,
`db` varchar(512) not null,
`last_insert_id` int(11) not null,
`insert_id` int(11) not null,
`server_id` int(10) unsigned not null,
`sql_text` mediumtext not null,
`thread_id` bigint(21) unsigned not null,
key `idx_start_time` (`start_time`),
key `idx_query_time` (`query_time`),
key `idx_lock_time` (`lock_time`),
key `idx_rows_examined` (`rows_examined`)
) engine=innodb default charset=utf8mb4;
-- insert into slow_log.slow_log_2019-05-30 select * from mysql.slow_log;
-- truncate table mysql.slow_log ;
select * from slow_log.`slow_log_2019-05-30`
where sql_text not like '***`%'
order by query_time desc,query_time desc;
按優先順序排列,需要關注的列是lock_time,query_time,rows_examined.分析的時候應用二八法則,先找出最坑爹的那部分sql,率先優化掉,然後不斷not like或者刪除掉排除掉已經優化好的低效sql.
低效sql的優化思路
對於每乙個查詢,先用explain sql分析一遍,是比較明智的做法.
一般而言,rows越少越好,提防extra:using where這種情況,這種情況一般是掃全表,在資料量大(>10萬)的時候考慮增加索引.
慎用子查詢
盡力避免巢狀子查詢,使用索引來優化它們explain select *
from (
select *
from `s`.`t`
where status in (-15, -11)
limit 0, 10
) aorder by a.modified desc
比如說這種的,根本毫無必要.表面上看,比去掉子查詢更快一點,實際上是因為mysql 5.7對子查詢進行了優化,生成了derived table,把結果集做了一層快取.
按照實際的場景分析發現,status這個字段沒有做索引,導致查詢變成了全表掃瞄(using where),加了索引後,問題解決.
json型別
json資料型別,如果存入的json很長,讀取出來自然越慢.在實際場景中,首先要確定是否有使用這一型別的必要,其次,盡量只取所需欄位.
見過這樣寫的where j_a like '%"sid":514572%'
這種行為明顯是對mysql不熟悉,mysql是有json提取函式的.where json_extract(j_a, "$[0].sid")=514572;
雖然也是全表掃瞄,但怎麼說也比like全模糊查詢好吧?
更好的做法,是通過虛擬欄位建索引
但是現階段mysql對json的索引做的是不夠的,如果json資料列過大,建議還是存mongodb(見過把12萬json存mysql的,那讀取速度簡直無語).
字串型別where a=1
用數字給字串型別的字段賦值會導致該字段上的索引失效.where a='1'
分組查詢
group by,count(x),sum(x),慎用.非常消耗cpu
group byselect col_1 from table_a where (col_2 > 7 or mtsp_col_2 > 0) and col_3 = 1 group by col_1
這種不涉及聚合查詢(count(x),sum(x))的group by明顯就是不合理的,去重複查詢效果更高點select distinct(col_1) from table_a where (col_2 > 7 or mtsp_col_2 > 0) and col_3 = 1 limit ***;
count(x),sum(x)
x 這個字段最好帶索引,不然就算篩選條件有索引也會很慢
order by x
x這欄位最好帶上索引,不然show processlist;裡面可能會出現大量creating sort index的結果
組合索引失效
組合索引有個最左匹配原則key 'idx_a' (a,b,c)where b='' and c =''
這時組合索引是無效的.
其他explain sql
desc sql# innodb_trx表主要是包含了正在innodb引擎中執行的所有事務的資訊,包括waiting for a lock和running的事務
select * from information_schema.innodb_trx;
select * from information_schema.innodb_locks;
select * from information_schema.innodb_lock_waits;
參考鏈結
mysql 慢查詢 MySQL慢查詢
一 簡介 開啟慢查詢日誌,可以讓mysql記錄下查詢超過指定時間的語句,通過定位分析效能的瓶頸,才能更好的優化資料庫系統的效能。二 引數說明 slow query log 慢查詢開啟狀態 slow query log file 慢查詢日誌存放的位置 這個目錄需要mysql的執行帳號的可寫許可權,一般...
mysql配置慢查詢 MYSQL慢查詢配置
mysql慢查詢配置 1.慢查詢有什麼用?它能記錄下所有執行超過long query time時間的sql語句,幫你找到執行慢的sql,方便我們對這些sql進行優化.2.如何開啟慢查詢?首先我們先檢視mysql伺服器的慢查詢狀態是否開啟.執行如下命令 我們可以看到當前log slow queries...
mysql 慢查詢 測試 MySQL慢查詢測試實踐
1.開啟慢查詢的目的 開啟慢查詢日誌,可以讓mysql記錄下查詢超過指定時間的語句,通過定位分析效能的瓶頸,才能更好的優化資料庫系統的效能。2.設定mysql慢查詢 方法一 全域性變數設定 臨時生效 將 slow query log 全域性變數設定為 on 狀態 mysql set global s...