如何定位慢查詢和如何分析 SQl 執(zhí)行效率

定位慢 SQL

定位慢 SQL 有如下兩種解決方案:
  • 查看慢查詢?nèi)罩敬_定已經(jīng)執(zhí)行完的慢查詢
  • show processlist 查看正在執(zhí)行的慢查詢

我們一起來了解下這兩種方法的使用場景和使用技巧测秸!

1.通過慢查詢?nèi)罩?br> 如果需要定位到慢查詢楷兽,一般的方法是通過慢查詢?nèi)罩緛聿樵兊模琈ySQL 的慢查詢?nèi)罩居脕碛涗浽?MySQL 中響應(yīng)時間超過參數(shù) long_query_time(單位秒测蹲,默認(rèn)值 10)設(shè)置的值并且掃描記錄數(shù)不小于 min_examined_row_limit(默認(rèn)值 0)的語句础淤,能夠幫我們找到執(zhí)行完的慢查詢崭放,方便我們對這些 SQL 進(jìn)行優(yōu)化。

默認(rèn)情況下鸽凶,慢查詢?nèi)罩局胁粫涗浌芾碚Z句币砂,可通過設(shè)置 log_slow_admin_statements = on 讓管理語句中的慢查詢也會記錄到慢查詢?nèi)罩局小?br> 默認(rèn)情況下,也不會記錄查詢時間不超過 long_query_time 但是不使用索引的語句玻侥,可通過配置 log_queries_not_using_indexes = on 讓不使用索引的 SQL 都被記錄到慢查詢?nèi)罩局校词共樵儠r間沒超過 long_query_time 配置的值)道伟。

使用慢查詢?nèi)罩荆话惴譃樗牟剑洪_啟慢查詢?nèi)罩臼鼓搿⒃O(shè)置慢查詢閥值蜜徽、確定慢查詢?nèi)罩韭窂健⒋_定慢查詢?nèi)罩镜奈募?

  • 首先開啟慢查詢?nèi)罩酒币。蓞?shù) slow_query_log 決定是否開啟拘鞋,在 MySQL 命令行下輸入下面的命令:
mysql> set global slow_query_log = on;

默認(rèn)環(huán)境下,慢查詢?nèi)罩臼顷P(guān)閉的矢门。

  • 設(shè)置慢查詢時間閥值
mysql> set global long_query_time = 1;

MySQL 中 long_query_time 的值如何確定呢盆色?
線上業(yè)務(wù)一般建議把 long_query_time 設(shè)置為 1 秒灰蛙,如果某個業(yè)務(wù)的 MySQL 要求比較高的 QPS,可設(shè)置慢查詢?yōu)?0.1 秒隔躲。發(fā)現(xiàn)慢查詢及時優(yōu)化或者提醒開發(fā)改寫摩梧。
一般測試環(huán)境建議 long_query_time 設(shè)置的閥值比生產(chǎn)環(huán)境的小耸采,比如生產(chǎn)環(huán)境是 1 秒掂林,則測試環(huán)境建議配置成 0.5 秒婶溯。便于在測試環(huán)境及時發(fā)現(xiàn)一些效率低的 SQL奶是。
甚至某些重要業(yè)務(wù)測試環(huán)境 long_query_time 可以設(shè)置為 0稀轨,以便記錄所有語句履肃。并留意慢查詢?nèi)罩镜妮敵鲎暮В暇€前的功能測試完成后突委,分析慢查詢?nèi)罩久款愓Z句的輸出,重點(diǎn)關(guān)注 Rows_examined(語句執(zhí)行期間從存儲引擎讀取的行數(shù)),提前優(yōu)化术陶。

  • 確定慢查詢?nèi)罩韭窂?/li>

慢查詢?nèi)罩镜穆窂侥J(rèn)是 MySQL 的數(shù)據(jù)目錄

mysql> show global variables like "datadir";
  • 確定慢查詢?nèi)罩镜奈募?/li>
show global variables like "slow_query_log_file";

根據(jù)上面的查詢結(jié)果獲取慢日志文件已經(jīng)執(zhí)行完的慢查詢:

[root@mysqltest ~]# tail -n5 /data/mysql/data/3306/mysql-slow.log

Time: 2019-05-21T09:15:06.255554+08:00

User@Host: root[root] @ localhost []  Id: 8591152

Query_time: 10.000260  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 0

SET timestamp=1558401306;
select sleep(10);

這里對上方的執(zhí)行結(jié)果詳細(xì)描述一下:
tail -n5:只查看慢查詢文件的最后 5 行
Time:慢查詢發(fā)生的時間
User@Host:客戶端用戶和 IP
Query_time:查詢時間
Lock_time:等待表鎖的時間
Rows_sent:語句返回的行數(shù)
Rows_examined:語句執(zhí)行期間從存儲引擎讀取的行數(shù)

2.通過 show processlist

有時慢查詢正在執(zhí)行,已經(jīng)導(dǎo)致數(shù)據(jù)庫負(fù)載偏高了腥椒,而由于慢查詢還沒執(zhí)行完,因此慢查詢?nèi)罩具€看不到任何語句候衍。此時可以使用 show processlist 命令判斷正在執(zhí)行的慢查詢寞酿。show processlist 顯示哪些線程正在運(yùn)行。如果有 PROCESS 權(quán)限脱柱,則可以看到所有線程伐弹。否則,只能看到當(dāng)前會話的線程榨为。

如果不使用 FULL 關(guān)鍵字惨好,在 info 字段中只顯示每個語句的前 100 個字符,如果想看語句的全部內(nèi)容可以使用 full 修飾(show full processlist)随闺。

mysql> show processlist\G`

`*************************** 10. row ***************************`

   `Id: 7651833`

   `User: one`

   `Host: 192.168.1.251:52154`

   `db: ops`

   `Command: Query`

   `Time: 3`

  `State: User sleep`

  `Info: select sleep(10)`

`......`

`10 rows in set (0.00 sec)`

這里對上面結(jié)果解釋一下:

    Time:表示執(zhí)行時間
    Info:表示 SQL 語句

我們這里可以通過它的執(zhí)行時間(Time)來判斷是否是慢 SQL日川。

使用 explain 分析慢查詢

分析 SQL 執(zhí)行效率是優(yōu)化 SQL 的重要手段,通過上面講的兩種方法矩乐,定位到慢查詢語句后龄句,我們可以通過 explain、show profile 和 trace 等診斷工具來分析慢查詢散罕。

Explain 可以獲取 MySQL 中 SQL 語句的執(zhí)行計劃分歇,比如語句是否使用了關(guān)聯(lián)查詢、是否使用了索引欧漱、掃描行數(shù)等职抡。可以幫我們選擇更好地索引和寫出更優(yōu)的 SQL 误甚。使用方法:在查詢語句前面加上 explain 運(yùn)行就可以了缚甩。

這也是分析 SQL 時最常用的谱净,也是作者最推薦的一種分析慢查詢的方式。下面我們來看下示例~~

為了便于理解擅威,先創(chuàng)建兩張測試表(方便第 1壕探、2 節(jié)實(shí)驗(yàn)使用),建表及數(shù)據(jù)寫入語句如下:

CREATE DATABASE test;   /* 創(chuàng)建測試使用的database郊丛,名為test */
use test;              /* 使用muke這個database */
drop table if exists t1;        /* 如果表t1存在則刪除表t1 */

CREATE TABLE `t1` (             /* 創(chuàng)建表t1 */
  `id` int(11) NOT NULL auto_increment,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '記錄創(chuàng)建時間',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '記錄更新時間',
  PRIMARY KEY (`id`),
  KEY `idx_a` (`a`),
  KEY `idx_b` (`b`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;    

drop procedure if exists insert_t1; /* 如果存在存儲過程insert_t1李请,則刪除 */
delimiter ;;
create procedure insert_t1()        /* 創(chuàng)建存儲過程insert_t1 */
begin
  declare i int;                    /* 聲明變量i */
  set i=1;                          /* 設(shè)置i的初始值為1 */
  while(i<=1000)do                  /* 對滿足i<=1000的值進(jìn)行while循環(huán) */
    insert into t1(a,b) values(i, i); /* 寫入表t1中a、b兩個字段宾袜,值都為i當(dāng)前的值 */
    set i=i+1;                      /* 將i加1 */
  end while;
end;;
delimiter ;                 /* 創(chuàng)建批量寫入1000條數(shù)據(jù)到表t1的存儲過程insert_t1 */
call insert_t1();           /* 運(yùn)行存儲過程insert_t1 */

drop table if exists t2;    /* 如果表t2存在則刪除表t2 */
create table t2 like t1;    /* 創(chuàng)建表t2捻艳,表結(jié)構(gòu)與t1一致 */
insert into t2 select * from t1;   /* 將表t1的數(shù)據(jù)導(dǎo)入到t2 */

下面嘗試使用 explain 分析一條 SQL驾窟,例子如下:

mysql> explain select * from t1 where b=100;

Explain 的結(jié)果各字段解釋如下庆猫,加粗的列為需要重點(diǎn)關(guān)注的項(xiàng):

  • id 查詢編號
  • select_type 查詢類型:顯示本行是簡單還是復(fù)雜查詢
  • table 涉及到的表
  • partitions 匹配的分區(qū):查詢將匹配記錄所在的分區(qū)。僅當(dāng)使用partition 關(guān)鍵字時才顯示該列绅络。對于非分區(qū)表月培,該值為 NULL。
  • type 本次查詢的表連接類型
  • possible_keys 可能選擇的索引
  • key 實(shí)際選擇的索引
  • key_len 被選擇的索引長度:一般用于判斷聯(lián)合索引有多少列被選擇了
  • ref 與索引比較的列
  • rows 預(yù)計需要掃描的行數(shù)恩急,對 InnoDB 來說杉畜,這個值是估值,并不一定準(zhǔn)確
  • filtered 按條件篩選的行的百分比
  • Extra 附加信息

下面將列出它們常見的一些值衷恭,可稍微過一遍此叠,不需要完全記下來,對比各種值的區(qū)別随珠。

Type.png

上表的這些情況灭袁,查詢性能從上到下依次是最好到最差。

Extra.png

Extra2.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窗看,一起剝皮案震驚了整個濱河市茸歧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌显沈,老刑警劉巖软瞎,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拉讯,居然都是意外死亡涤浇,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門魔慷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芙代,“玉大人,你說我怎么就攤上這事盖彭∥婆耄” “怎么了页滚?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铺呵。 經(jīng)常有香客問我裹驰,道長,這世上最難降的妖魔是什么片挂? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任幻林,我火速辦了婚禮,結(jié)果婚禮上音念,老公的妹妹穿的比我還像新娘沪饺。我一直安慰自己,他們只是感情好闷愤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布整葡。 她就那樣靜靜地躺著,像睡著了一般讥脐。 火紅的嫁衣襯著肌膚如雪遭居。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天旬渠,我揣著相機(jī)與錄音俱萍,去河邊找鬼。 笑死告丢,一個胖子當(dāng)著我的面吹牛枪蘑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播岖免,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼岳颇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了觅捆?” 一聲冷哼從身側(cè)響起赦役,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎栅炒,沒想到半個月后掂摔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赢赊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年乙漓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片释移。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡叭披,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出玩讳,到底是詐尸還是另有隱情涩蜘,我是刑警寧澤嚼贡,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站同诫,受9級特大地震影響粤策,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜误窖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一叮盘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧霹俺,春花似錦柔吼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至艇棕,卻和暖如春蝌戒,著一層夾襖步出監(jiān)牢的瞬間串塑,已是汗流浹背沼琉。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留桩匪,地道東北人打瘪。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像傻昙,于是被迫代替她去往敵國和親闺骚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容