溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

在mysql如何查找效率慢的SQL語句

發(fā)布時(shí)間:2021-10-29 17:50:12 來源:億速云 閱讀:208 作者:小新 欄目:MySQL數(shù)據(jù)庫

這篇文章主要介紹在mysql如何查找效率慢的SQL語句,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!


一、MySQL數(shù)據(jù)庫有幾個(gè)配置選項(xiàng)可以幫助我們及時(shí)捕獲低效SQL語句
1,slow_query_log
這個(gè)參數(shù)設(shè)置為ON,可以捕獲執(zhí)行時(shí)間超過一定數(shù)值的SQL語句。
2,long_query_time
當(dāng)SQL語句執(zhí)行時(shí)間超過此數(shù)值時(shí),就會(huì)被記錄到日志中,建議設(shè)置為1或者更短。
3,slow_query_log_file
記錄日志的文件名。
4,log_queries_not_using_indexes
這個(gè)參數(shù)設(shè)置為ON,可以捕獲到所有未使用索引的SQL語句,盡管這個(gè)SQL語句有可能執(zhí)行得挺快。
二、檢測mysql中sql語句的效率的方法
1、通過查詢?nèi)罩?br/>(1)、Windows下開啟MySQL慢查詢
MySQL在Windows系統(tǒng)中的配置文件一般是是my.ini找到[mysqld]下面加上
代碼如下
log-slow-queries = F:/MySQL/log/mysqlslowquery。log
long_query_time = 2

(2)、Linux下啟用MySQL慢查詢
MySQL在Windows系統(tǒng)中的配置文件一般是是my.cnf找到[mysqld]下面加上
代碼如下
log-slow-queries=/data/mysqldata/slowquery。log
long_query_time=2
說明
log-slow-queries = F:/MySQL/log/mysqlslowquery。
為慢查詢?nèi)罩敬娣诺奈恢?,一般這個(gè)目錄要有MySQL的運(yùn)行帳號(hào)的可寫權(quán)限,一般都將這個(gè)目錄設(shè)置為MySQL的數(shù)據(jù)存放目錄;
long_query_time=2中的2表示查詢超過兩秒才記錄;

2.show processlist 命令
WSHOW PROCESSLIST顯示哪些線程正在運(yùn)行。您也可以使用mysqladmin processlist語句得到此信息。
各列的含義和用途:
ID列
一個(gè)標(biāo)識(shí),你要kill一個(gè)語句的時(shí)候很有用,用命令殺掉此查詢 /*/mysqladmin kill 進(jìn)程號(hào)。
user列
顯示單前用戶,如果不是root,這個(gè)命令就只顯示你權(quán)限范圍內(nèi)的sql語句。
host列
顯示這個(gè)語句是從哪個(gè)ip的哪個(gè)端口上發(fā)出的。用于追蹤出問題語句的用戶。
db列
顯示這個(gè)進(jìn)程目前連接的是哪個(gè)數(shù)據(jù)庫。
command列
顯示當(dāng)前連接的執(zhí)行的命令,一般就是休眠(sleep),查詢(query),連接(connect)。
time列
此這個(gè)狀態(tài)持續(xù)的時(shí)間,單位是秒。
state列
顯示使用當(dāng)前連接的sql語句的狀態(tài),很重要的列,后續(xù)會(huì)有所有的狀態(tài)的描述,請注意,state只是語句執(zhí)行中的某一個(gè)狀態(tài),一個(gè) sql語句,以查詢?yōu)槔赡苄枰?jīng)過copying to tmp table,Sorting result,Sending data等狀態(tài)才可以完成
info列
顯示這個(gè)sql語句,因?yàn)殚L度有限,所以長的sql語句就顯示不全,但是一個(gè)判斷問題語句的重要依據(jù)。
這個(gè)命令中最關(guān)鍵的就是state列,mysql列出的狀態(tài)主要有以下幾種:
Checking table
 正在檢查數(shù)據(jù)表(這是自動(dòng)的)。
Closing tables
 正在將表中修改的數(shù)據(jù)刷新到磁盤中,同時(shí)正在關(guān)閉已經(jīng)用完的表。這是一個(gè)很快的操作,如果不是這樣的話,就應(yīng)該確認(rèn)磁盤空間是否已經(jīng)滿了或者磁盤是否正處于重負(fù)中。
Connect Out
 復(fù)制從服務(wù)器正在連接主服務(wù)器。
Copying to tmp table on disk
 由于臨時(shí)結(jié)果集大于tmp_table_size,正在將臨時(shí)表從內(nèi)存存儲(chǔ)轉(zhuǎn)為磁盤存儲(chǔ)以此節(jié)省內(nèi)存。
Creating tmp table
 正在創(chuàng)建臨時(shí)表以存放部分查詢結(jié)果。
deleting from main table
 服務(wù)器正在執(zhí)行多表刪除中的第一部分,剛刪除第一個(gè)表。
deleting from reference tables
 服務(wù)器正在執(zhí)行多表刪除中的第二部分,正在刪除其他表的記錄。
Flushing tables
 正在執(zhí)行FLUSH TABLES,等待其他線程關(guān)閉數(shù)據(jù)表。
Killed
 發(fā)送了一個(gè)kill請求給某線程,那么這個(gè)線程將會(huì)檢查kill標(biāo)志位,同時(shí)會(huì)放棄下一個(gè)kill請求。MySQL會(huì)在每次的主循環(huán)中檢查kill標(biāo)志位,不過有些情況下該線程可能會(huì)過一小段才能死掉。如果該線程程被其他線程鎖住了,那么kill請求會(huì)在鎖釋放時(shí)馬上生效。
Locked
 被其他查詢鎖住了。
Sending data
 正在處理SELECT查詢的記錄,同時(shí)正在把結(jié)果發(fā)送給客戶端。
Sorting for group
 正在為GROUP BY做排序。
 Sorting for order
 正在為ORDER BY做排序。
Opening tables
 這個(gè)過程應(yīng)該會(huì)很快,除非受到其他因素的干擾。例如,在執(zhí)ALTER TABLE或LOCK TABLE語句行完以前,數(shù)據(jù)表無法被其他線程打開。正嘗試打開一個(gè)表。
Removing duplicates
 正在執(zhí)行一個(gè)SELECT DISTINCT方式的查詢,但是MySQL無法在前一個(gè)階段優(yōu)化掉那些重復(fù)的記錄。因此,MySQL需要再次去掉重復(fù)的記錄,然后再把結(jié)果發(fā)送給客戶端。
Reopen table
 獲得了對一個(gè)表的鎖,但是必須在表結(jié)構(gòu)修改之后才能獲得這個(gè)鎖。已經(jīng)釋放鎖,關(guān)閉數(shù)據(jù)表,正嘗試重新打開數(shù)據(jù)表。
Repair by sorting
 修復(fù)指令正在排序以創(chuàng)建索引。
Repair with keycache
 修復(fù)指令正在利用索引緩存一個(gè)一個(gè)地創(chuàng)建新索引。它會(huì)比Repair by sorting慢些。
Searching rows for update
 正在講符合條件的記錄找出來以備更新。它必須在UPDATE要修改相關(guān)的記錄之前就完成了。
Sleeping
 正在等待客戶端發(fā)送新請求.
System lock
 正在等待取得一個(gè)外部的系統(tǒng)鎖。如果當(dāng)前沒有運(yùn)行多個(gè)mysqld服務(wù)器同時(shí)請求同一個(gè)表,那么可以通過增加--skip-external-locking參數(shù)來禁止外部系統(tǒng)鎖。
Upgrading lock
 INSERT DELAYED正在嘗試取得一個(gè)鎖表以插入新記錄。
Updating
 正在搜索匹配的記錄,并且修改它們。
User Lock
 正在等待GET_LOCK()。
Waiting for tables
 該線程得到通知,數(shù)據(jù)表結(jié)構(gòu)已經(jīng)被修改了,需要重新打開數(shù)據(jù)表以取得新的結(jié)構(gòu)。然后,為了能的重新打開數(shù)據(jù)表,必須等到所有其他線程關(guān)閉這個(gè)表。以下幾種情況下會(huì)產(chǎn)生這個(gè)通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE,或OPTIMIZE TABLE。
waiting for handler insert
 INSERT DELAYED已經(jīng)處理完了所有待處理的插入操作,正在等待新的請求。
 大部分狀態(tài)對應(yīng)很快的操作,只要有一個(gè)線程保持同一個(gè)狀態(tài)好幾秒鐘,那么可能是有問題發(fā)生了,需要檢查一下。
 還有其他的狀態(tài)沒在上面中列出來,不過它們大部分只是在查看服務(wù)器是否有存在錯(cuò)誤是才用得著。
例如如圖:

3、explain來了解SQL執(zhí)行的狀態(tài)
explain顯示了mysql如何使用索引來處理select語句以及連接表??梢詭椭x擇更好的索引和寫出更優(yōu)化的查詢語句。
使用方法,在select語句前加上explain就可以了:
例如:
 
1
explain select surname,first_name form a,b where a.id=b.id
結(jié)果如圖

EXPLAIN列的解釋
table
顯示這一行的數(shù)據(jù)是關(guān)于哪張表的
type
這是重要的列,顯示連接使用了何種類型。從最好到最差的連接類型為const、eq_reg、ref、range、indexhe和ALL
possible_keys
顯示可能應(yīng)用在這張表中的索引。如果為空,沒有可能的索引??梢詾橄嚓P(guān)的域從WHERE語句中選擇一個(gè)合適的語句
key
實(shí)際使用的索引。如果為NULL,則沒有使用索引。很少的情況下,MYSQL會(huì)選擇優(yōu)化不足的索引。這種情況下,可以在SELECT語句 中使用USE INDEX(indexname)來強(qiáng)制使用一個(gè)索引或者用IGNORE INDEX(indexname)來強(qiáng)制MYSQL忽略索引
key_len
使用的索引的長度。在不損失精確性的情況下,長度越短越好
ref
顯示索引的哪一列被使用了,如果可能的話,是一個(gè)常數(shù)
rows
MYSQL認(rèn)為必須檢查的用來返回請求數(shù)據(jù)的行數(shù)
Extra
關(guān)于MYSQL如何解析查詢的額外信息。將在表4.3中討論,但這里可以看到的壞的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,結(jié)果是檢索會(huì)很慢
 extra列返回的描述的意義
Distinct
一旦MYSQL找到了與行相聯(lián)合匹配的行,就不再搜索了
Not exists
MYSQL優(yōu)化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標(biāo)準(zhǔn)的行,就不再搜索了
Range checked for each Record(index map:#)
沒有找到理想的索引,因此對于從前面表中來的每一個(gè)行組合,MYSQL檢查使用哪個(gè)索引,并用它來從表中返回行。這是使用索引的最慢的連接之一
Using filesort
看到這個(gè)的時(shí)候,查詢就需要優(yōu)化了。MYSQL需要進(jìn)行額外的步驟來發(fā)現(xiàn)如何對返回的行排序。它根據(jù)連接類型以及存儲(chǔ)排序鍵值和匹配條件的全部行的行指針來排序全部行
Using index
列數(shù)據(jù)是從僅僅使用了索引中的信息而沒有讀取實(shí)際的行動(dòng)的表返回的,這發(fā)生在對表的全部的請求列都是同一個(gè)索引的部分的時(shí)候
Using temporary
看到這個(gè)的時(shí)候,查詢需要優(yōu)化了。這里,MYSQL需要?jiǎng)?chuàng)建一個(gè)臨時(shí)表來存儲(chǔ)結(jié)果,這通常發(fā)生在對不同的列集進(jìn)行ORDER BY上,而不是GROUP BY上
Where used
使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給用戶。如果不想返回表中的全部行,并且連接類型ALL或index,這就會(huì)發(fā)生,或者是查詢有問題不同連接類型的解釋(按照效率高低的順序排序)
const
表中的一個(gè)記錄的最大值能夠匹配這個(gè)查詢(索引可以是主鍵或惟一索引)。因?yàn)橹挥幸恍?,這個(gè)值實(shí)際就是常數(shù),因?yàn)镸YSQL先讀這個(gè)值然后把它當(dāng)做常數(shù)來對待
eq_ref
在連接中,MYSQL在查詢時(shí),從前面的表中,對每一個(gè)記錄的聯(lián)合都從表中讀取一個(gè)記錄,它在查詢使用了索引為主鍵或惟一鍵的全部時(shí)使用
ref
這個(gè)連接類型只有在查詢使用了不是惟一或主鍵的鍵或者是這些類型的部分(比如,利用最左邊前綴)時(shí)發(fā)生。對于之前的表的每一個(gè)行聯(lián)合,全部記錄都將從表中讀出。這個(gè)類型嚴(yán)重依賴于根據(jù)索引匹配的記錄多少—越少越好
range
這個(gè)連接類型使用索引返回一個(gè)范圍中的行,比如使用>或<查找東西時(shí)發(fā)生的情況
index
這個(gè)連接類型對前面的表中的每一個(gè)記錄聯(lián)合進(jìn)行完全掃描(比ALL更好,因?yàn)樗饕话阈∮诒頂?shù)據(jù))
ALL
這個(gè)連接類型對于前面的每一個(gè)記錄聯(lián)合進(jìn)行完全掃描,這一般比較糟糕,應(yīng)該盡量避免

MySQL - 查看慢SQL
查看MySQL是否啟用了查看慢SQL的日志文件
(1) 查看慢SQL日志是否啟用
mysql> show variables like 'log_slow_queries';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| log_slow_queries | ON    |
+------------------+-------+
1 row in set (0.00 sec)
(2) 查看執(zhí)行慢于多少秒的SQL會(huì)記錄到日志文件中
mysql> show variables like 'long_query_time';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| long_query_time | 1     |  
+-----------------+-------+
1 row in set (0.00 sec)
這里value=1, 表示1秒
2. 配置my.ini文件(inux下文件名為my.cnf), 查找到[mysqld]區(qū)段,增加日志的配置,如下示例:
[mysqld]
log="C:/temp/mysql.log"
log_slow_queries="C:/temp/mysql_slow.log"
long_query_time=1
log指示日志文件存放目錄;
log_slow_queries指示記錄執(zhí)行時(shí)間長的sql日志目錄;
long_query_time指示多長時(shí)間算是執(zhí)行時(shí)間長,單位s。
Linux下這些配置項(xiàng)應(yīng)該已經(jīng)存在,只是被注釋掉了,可以去掉注釋。但直接添加配置項(xiàng)也OK啦。
查詢到效率低的 SQL 語句 后,可以通過 EXPLAIN 或者 DESC 命令獲取 MySQL 如何執(zhí)行 SELECT 語句的信息,包括在 SELECT 語句執(zhí)行過程中表如何連接和連接的順序,比如我們想計(jì)算 2006 年所有公司的銷售額,需要關(guān)聯(lián) sales 表和 company 表,并且對 profit 字段做求和( sum )操作,相應(yīng) SQL 的執(zhí)行計(jì)劃如下:
mysql> explain select sum(profit) from sales a,company b where a.company_id = b.id and a.year = 2006\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: a
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 12
Extra: Using where
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: b
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 12
Extra: Using where
2 rows in set (0.00 sec)
每個(gè)列的解釋如下:
?select_type :表示 SELECT 的 類型,常見的取值有 SIMPLE (簡單表,即不使用表連接或者子查詢)、 PRIMARY (主查詢,即外層的查詢)、 UNION ( UNION 中的第二個(gè)或者后面的查詢語句)、 SUBQUERY (子查詢中的第一個(gè) SELECT )等。
?table :輸出結(jié)果集的表。
?type :表示表的連接類型,性能由好到差的連接類型為 system (表中僅有一行,即常量表)、 const (單表中最多有一個(gè)匹配行,例如 primary key 或者 unique index )、 eq_ref (對于前面的每一行,在此表中只查詢一條記錄,簡單來說,就是多表連接中使用 primary key 或者 unique index )、 ref (與 eq_ref 類似,區(qū)別在于不是使用 primary key 或者 unique index ,而是使用普通的索引)、 ref_or_null ( 與 ref 類似,區(qū)別在于條件中包含對 NULL 的查詢 ) 、 index_merge ( 索引合并優(yōu)化 ) 、 unique_subquery ( in 的后面是一個(gè)查詢主鍵字段的子查詢)、 index_subquery ( 與 unique_subquery 類似,區(qū)別在于 in 的后面是查詢非唯一索引字段的子查詢)、 range (單表中的范圍查詢)、 index (對于前面的每一行,都通過查詢索引來得到數(shù)據(jù))、 all (對于前面的每一行,都通過全表掃描來得到數(shù)據(jù))。
?possible_keys :表示查詢時(shí),可能使用的索引。
?key :表示實(shí)際使用的索引。
?key_len :索引字段的長度。
?rows :掃描行的數(shù)量。
?Extra :執(zhí)行情況的說明和描述。
在上面的例子中,已經(jīng)可以確認(rèn)是 對 a 表的全表掃描導(dǎo)致效率的不理想,那么 對 a 表的 year 字段創(chuàng)建索引,具體如下:
mysql> create index idx_sales_year on sales(year);
Query OK, 12 rows affected (0.01 sec)
Records: 12 Duplicates: 0 Warnings: 0
創(chuàng)建索引后,這條語句的執(zhí)行計(jì)劃如下:
mysql> explain select sum(profit) from sales a,company b where a.company_id = b.id and a.year = 2006\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: a
type: ref
possible_keys: idx_sales_year
key: idx_sales_year
key_len: 4
ref: const
rows: 3
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: b
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 12
Extra: Using where
2 rows in set (0.00 sec)
可以發(fā)現(xiàn)建立索引后對 a 表需要掃描的行數(shù)明顯減少(從全表掃描減少到 3 行),可見索引的使用可以大大提高數(shù)據(jù)庫的訪問速度,尤其在表很龐大的時(shí)候這種優(yōu)勢更為明顯,使用索引優(yōu)化 sql 是優(yōu)化問題 sql 的一種常用基本方法,在后面的章節(jié)中我們會(huì)具體介紹如何使索引來優(yōu)化 sql 。
本文主要介紹的是MySQL慢查詢分析方法,前一段日子,我曾經(jīng)設(shè)置了一次記錄在MySQL數(shù)據(jù)庫中對慢于1秒鐘的SQL語句進(jìn)行查詢。想起來有幾個(gè)十分設(shè)置的方法,有幾個(gè)參數(shù)的名稱死活回憶不起來了,于是重新整理一下,自己做個(gè)筆記。
  對于排查問題找出性能瓶頸來說,最容易發(fā)現(xiàn)并解決的問題就是MySQL慢查詢以及沒有得用索引的查詢。
  OK,開始找出MySQL中執(zhí)行起來不“爽”的SQL語句吧。
  MySQL慢查詢分析方法一:
  這個(gè)方法我正在用,呵呵,比較喜歡這種即時(shí)性的。
  MySQL5.0以上的版本可以支持將執(zhí)行比較慢的SQL語句記錄下來。
  MySQL> show variables like 'long%';
  注:這個(gè)long_query_time是用來定義慢于多少秒的才算“慢查詢”
  +-----------------+-----------+
  | Variable_name | Value |
  +-----------------+-----------+
  | long_query_time | 10.000000 |
  +-----------------+-----------+
  1 row in set (0.00 sec)
  MySQL> set long_query_time=1;
  注: 我設(shè)置了1, 也就是執(zhí)行時(shí)間超過1秒的都算慢查詢。
  Query OK, 0 rows affected (0.00 sec)
  MySQL> show variables like 'slow%';
  +---------------------+---------------+
  | Variable_name | Value |
  +---------------------+---------------+
  | slow_launch_time | 2 |
  | slow_query_log | ON |
  注:是否打開日志記錄
  | slow_query_log_file | /tmp/slow.log |
  注: 設(shè)置到什么位置
  +---------------------+---------------+
  3 rows in set (0.00 sec)
  MySQL> set global slow_query_log='ON'
  注:打開日志記錄
  一旦slow_query_log變量被設(shè)置為ON,MySQL會(huì)立即開始記錄。
  /etc/my.cnf 里面可以設(shè)置上面MySQL全局變量的初始值。
  long_query_time=1 slow_query_log_file=/tmp/slow.log
  MySQL慢查詢分析方法二:
  MySQLdumpslow命令
  /path/MySQLdumpslow -s c -t 10 /tmp/slow-log
  這會(huì)輸出記錄次數(shù)最多的10條SQL語句,其中:
  -s, 是表示按照何種方式排序,c、t、l、r分別是按照記錄次數(shù)、時(shí)間、查詢時(shí)間、返回的記錄數(shù)來排序,ac、at、al、ar,表示相應(yīng)的倒敘;
  -t, 是top n的意思,即為返回前面多少條的數(shù)據(jù);
  -g, 后邊可以寫一個(gè)正則匹配模式,大小寫不敏感的;
  比如
  /path/MySQLdumpslow -s r -t 10 /tmp/slow-log
  得到返回記錄集最多的10個(gè)查詢。
  /path/MySQLdumpslow -s t -t 10 -g “l(fā)eft join” /tmp/slow-log
  得到按照時(shí)間排序的前10條里面含有左連接的查詢語句。
 
簡單點(diǎn)的方法:
打開 my.ini ,找到 [mysqld] 在其下面添加   long_query_time = 2 log-slow-queries = D:/mysql/logs/slow.log #設(shè)置把日志寫在那里,可以為空,系統(tǒng)會(huì)給一個(gè)缺省的文件 #log-slow-queries = /var/youpath/slow.log linux下host_name-slow.log log-queries-not-using-indexes   long_query_time 是指執(zhí)行超過多長時(shí)間(單位是秒)的sql會(huì)被記錄下來,這里設(shè)置的是2秒。
以下是mysqldumpslow常用參數(shù)說明,詳細(xì)的可應(yīng)用mysqldumpslow -help查詢。   -s,是表示按照何種方式排序,c、t、l、r分別是按照記錄次數(shù)、時(shí)間、查詢時(shí)間、返回的記錄數(shù)來排序(從大到?。?,ac、at、al、ar表示相應(yīng)的倒敘。   -t,是top n的意思,即為返回前面多少條數(shù)據(jù)。 www.jb51.net  -g,后邊可以寫一個(gè)正則匹配模式,大小寫不敏感。   接下來就是用mysql自帶的慢查詢工具mysqldumpslow分析了(mysql的bin目錄下 ),我這里的日志文件名字是host-slow.log。   列出記錄次數(shù)最多的10個(gè)sql語句   mysqldumpslow -s c -t 10 host-slow.log   列出返回記錄集最多的10個(gè)sql語句  mysqldumpslow -s r -t 10 host-slow.log   按照時(shí)間返回前10條里面含有左連接的sql語句   mysqldumpslow -s t -t 10 -g "left join" host-slow.log   使用mysqldumpslow命令可以非常明確的得到各種我們需要的查詢語句,對MySQL查詢語句的監(jiān)控、分析、優(yōu)化起到非常大的幫助
 
在日常開發(fā)當(dāng)中,經(jīng)常會(huì)遇到頁面打開速度極慢的情況,通過排除,確定了,是數(shù)據(jù)庫的影響,為了迅速查找具體的SQL,可以通過Mysql的日志記錄方法。
-- 打開sql執(zhí)行記錄功能
set global log_output='TABLE'; -- 輸出到表
set global log=ON; -- 打開所有命令執(zhí)行記錄功能general_log, 所有語句: 成功和未成功的.
set global log_slow_queries=ON; -- 打開慢查詢sql記錄slow_log, 執(zhí)行成功的: 慢查詢語句和未使用索引的語句
set global long_query_time=0.1; -- 慢查詢時(shí)間限制(秒)
set global log_queries_not_using_indexes=ON; -- 記錄未使用索引的sql語句
-- 查詢sql執(zhí)行記錄
select * from mysql.slow_log order by 1; -- 執(zhí)行成功的:慢查詢語句,和未使用索引的語句
select * from mysql.general_log order by 1; -- 所有語句: 成功和未成功的.
-- 關(guān)閉sql執(zhí)行記錄
set global log=OFF;
set global log_slow_queries=OFF;
-- long_query_time參數(shù)說明
-- v4.0, 4.1, 5.0, v5.1 到 5.1.20(包括):不支持毫秒級別的慢查詢分析(支持精度為1-10秒);
-- 5.1.21及以后版本 :支持毫秒級別的慢查詢分析, 如0.1;
-- 6.0 到 6.0.3: 不支持毫秒級別的慢查詢分析(支持精度為1-10秒);
-- 6.0.4及以后:支持毫秒級別的慢查詢分析;
通過日志中記錄的Sql,迅速定位到具體的文件,優(yōu)化sql看一下,是否速度提升了呢?
 
本文針對MySQL數(shù)據(jù)庫服務(wù)器查詢逐漸變慢的問題, 進(jìn)行分析,并提出相應(yīng)的解決辦法,具體的分析解決辦法如下:會(huì)經(jīng)常發(fā)現(xiàn)開發(fā)人員查一下沒用索引的語句或者沒有l(wèi)imit n的語句,這些沒語句會(huì)對數(shù)據(jù)庫造成很大的影...
 
本文針對MySQL數(shù)據(jù)庫服務(wù)器查詢逐漸變慢的問題, 進(jìn)行分析,并提出相應(yīng)的解決辦法,具體的分析解決辦法如下:
會(huì)經(jīng)常發(fā)現(xiàn)開發(fā)人員查一下沒用索引的語句或者沒有l(wèi)imit n的語句,這些沒語句會(huì)對數(shù)據(jù)庫造成很大的影響,例如一個(gè)幾千萬條記錄的大表要全部掃描,或者是不停的做filesort,對數(shù)據(jù)庫和服務(wù)器造成io影響等。這是鏡像庫上面的情況。
而到了線上庫,除了出現(xiàn)沒有索引的語句,沒有用limit的語句,還多了一個(gè)情況,mysql連接數(shù)過多的問題。說到這里,先來看看以前我們的監(jiān)控做法
1. 部署zabbix等開源分布式監(jiān)控系統(tǒng),獲取每天的數(shù)據(jù)庫的io,cpu,連接數(shù)
2. 部署每周性能統(tǒng)計(jì),包含數(shù)據(jù)增加量,iostat,vmstat,datasize的情況
3. Mysql slowlog收集,列出top 10
以前以為做了這些監(jiān)控已經(jīng)是很完美了,現(xiàn)在部署了mysql節(jié)點(diǎn)進(jìn)程監(jiān)控之后,才發(fā)現(xiàn)很多弊端
第一種做法的弊端: zabbix太龐大,而且不是在mysql內(nèi)部做的監(jiān)控,很多數(shù)據(jù)不是非常準(zhǔn)備,現(xiàn)在一般都是用來查閱歷史的數(shù)據(jù)情況
第二種做法的弊端:因?yàn)槭敲恐苤慌芤淮?,很多情況沒法發(fā)現(xiàn)和報(bào)警
第三種做法的弊端: 當(dāng)節(jié)點(diǎn)的slowlog非常多的時(shí)候,top10就變得沒意義了,而且很多時(shí)候會(huì)給出那些是一定要跑的定期任務(wù)語句給你。。參考的價(jià)值不大
那么我們怎么來解決和查詢這些問題呢
對于排查問題找出性能瓶頸來說,最容易發(fā)現(xiàn)并解決的問題就是MYSQL的慢查詢以及沒有得用索引的查詢。
OK,開始找出mysql中執(zhí)行起來不“爽”的SQL語句吧。
方法一: 這個(gè)方法我正在用,呵呵,比較喜歡這種即時(shí)性的。
Mysql5.0以上的版本可以支持將執(zhí)行比較慢的SQL語句記錄下來。
 mysql> show variables like 'long%'; 注:這個(gè)long_query_time是用來定義慢于多少秒的才算“慢查詢”
 +-----------------+-----------+
 | Variable_name | Value |
 +-----------------+-----------+
 | long_query_time | 10.000000 |
 +-----------------+-----------+
 1 row in set (0.00 sec)
 mysql> set long_query_time=1; 注: 我設(shè)置了1, 也就是執(zhí)行時(shí)間超過1秒的都算慢查詢。
 Query OK, 0 rows affected (0.00 sec)
 mysql> show variables like 'slow%';
 +---------------------+---------------+
 | Variable_name | Value |
 +---------------------+---------------+
 | slow_launch_time | 2 |
 | slow_query_log | ON | 注:是否打開日志記錄
 | slow_query_log_file | /tmp/slow.log | 注: 設(shè)置到什么位置
 +---------------------+---------------+
 3 rows in set (0.00 sec)
 mysql> set global slow_query_log='ON' 注:打開日志記錄
 一旦slow_query_log變量被設(shè)置為ON,mysql會(huì)立即開始記錄。
 /etc/my.cnf 里面可以設(shè)置上面MYSQL全局變量的初始值。
 long_query_time=1
 slow_query_log_file=/tmp/slow.log
方法二:mysqldumpslow命令
 /path/mysqldumpslow -s c -t 10 /tmp/slow-log
 這會(huì)輸出記錄次數(shù)最多的10條SQL語句,其中:
 -s, 是表示按照何種方式排序,c、t、l、r分別是按照記錄次數(shù)、時(shí)間、查詢時(shí)間、返回的記錄數(shù)來排序,ac、at、al、ar,表示相應(yīng)的倒敘;
 -t, 是top n的意思,即為返回前面多少條的數(shù)據(jù);
 -g, 后邊可以寫一個(gè)正則匹配模式,大小寫不敏感的;
 比如
 /path/mysqldumpslow -s r -t 10 /tmp/slow-log
 得到返回記錄集最多的10個(gè)查詢。
 /path/mysqldumpslow -s t -t 10 -g “l(fā)eft join” /tmp/slow-log
 得到按照時(shí)間排序的前10條里面含有左連接的查詢語句。
最后總結(jié)一下節(jié)點(diǎn)監(jiān)控的好處
1. 輕量級的監(jiān)控,而且是實(shí)時(shí)的,還可以根據(jù)實(shí)際的情況來定制和修改
2. 設(shè)置了過濾程序,可以對那些一定要跑的語句進(jìn)行過濾
3. 及時(shí)發(fā)現(xiàn)那些沒有用索引,或者是不合法的查詢,雖然這很耗時(shí)去處理那些慢語句,但這樣可以避免數(shù)據(jù)庫掛掉,還是值得的
4. 在數(shù)據(jù)庫出現(xiàn)連接數(shù)過多的時(shí)候,程序會(huì)自動(dòng)保存當(dāng)前數(shù)據(jù)庫的processlist,DBA進(jìn)行原因查找的時(shí)候這可是利器
5. 使用mysqlbinlog 來分析的時(shí)候,可以得到明確的數(shù)據(jù)庫狀態(tài)異常的時(shí)間段
有些人會(huì)建義我們來做mysql配置文件設(shè)置
調(diào)節(jié)tmp_table_size 的時(shí)候發(fā)現(xiàn)另外一些參數(shù)
Qcache_queries_in_cache 在緩存中已注冊的查詢數(shù)目
Qcache_inserts 被加入到緩存中的查詢數(shù)目
Qcache_hits 緩存采樣數(shù)數(shù)目
Qcache_lowmem_prunes 因?yàn)槿鄙賰?nèi)存而被從緩存中刪除的查詢數(shù)目
Qcache_not_cached 沒有被緩存的查詢數(shù)目 (不能被緩存的,或由于 QUERY_CACHE_TYPE)
Qcache_free_memory 查詢緩存的空閑內(nèi)存總數(shù)
Qcache_free_blocks 查詢緩存中的空閑內(nèi)存塊的數(shù)目
Qcache_total_blocks 查詢緩存中的塊的總數(shù)目
Qcache_free_memory 可以緩存一些常用的查詢,如果是常用的sql會(huì)被裝載到內(nèi)存。那樣會(huì)增加數(shù)據(jù)庫訪問速度

以上是“在mysql如何查找效率慢的SQL語句”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI