MySQL慢查詢:慢SQL定位棒掠、日志分析與優(yōu)化方案

一個(gè)sql執(zhí)行很慢的就叫慢sql,一般來(lái)說(shuō)sql語(yǔ)句執(zhí)行超過(guò)5s就能夠算是慢sql恍飘,需要進(jìn)行優(yōu)化了

為何要對(duì)慢SQL進(jìn)行治理

每一個(gè)SQL都需要消耗一定的I/O資源榨崩,SQL執(zhí)行的快慢直接決定了資源被占用時(shí)間的長(zhǎng)短。假設(shè)業(yè)務(wù)要求每秒需要完成100條SQL的執(zhí)行章母,而其中10條SQL執(zhí)行時(shí)間長(zhǎng)導(dǎo)致每秒只能完成90條SQL母蛛,所有新的SQL將進(jìn)入排隊(duì)等待,直接影響業(yè)務(wù)

治理的優(yōu)先級(jí)

  • master數(shù)據(jù)庫(kù)->slave數(shù)據(jù)庫(kù):采用讀寫分離架構(gòu)乳怎,讀在從庫(kù)slave上執(zhí)行彩郊,寫在主庫(kù)master上執(zhí)行。但由于從庫(kù)的數(shù)據(jù)都是在主庫(kù)復(fù)制過(guò)去的蚪缀,主庫(kù)如果等待較多的情況秫逝,會(huì)加大從庫(kù)的復(fù)制延時(shí)
  • 執(zhí)行SQL次數(shù)多的優(yōu)先治理
  • 某張表被告并發(fā)集中訪問(wèn)的優(yōu)先治理

MySQL執(zhí)行原理

為了更好的優(yōu)化慢SQL,我們來(lái)簡(jiǎn)單了解下MySQL的執(zhí)行原理

image.png

綠色部分為SQL實(shí)際執(zhí)行部分椿胯,主要分為兩步:

  • 解析:詞法解析->語(yǔ)法解析->邏輯計(jì)劃->查詢優(yōu)化->物理執(zhí)行計(jì)劃筷登,過(guò)程中會(huì)檢查緩存是否可用剃根,如果沒(méi)有可用緩存則進(jìn)入下一步mysql_execute_command執(zhí)行
  • 執(zhí)行:檢查用戶哩盲、表權(quán)限->表加上共享讀鎖->取數(shù)據(jù)到query_cache->取消共享讀鎖

如何發(fā)現(xiàn)慢查詢SQL

-- 修改慢查詢時(shí)間,只能當(dāng)前會(huì)話有效?
set long_query_time=1? -
-- 啟用慢查詢 ,加上global,不然會(huì)報(bào)錯(cuò)的?
set global slow_query_log='ON'?-- 
-- 是否開啟慢查詢?
show variables like "%slow%"?-- 
-- 查詢慢查詢SQL狀況?
show status like "%slow%"? -- 
-- 慢查詢時(shí)間(默認(rèn)情況下MySQL認(rèn)位10秒以上才是慢查詢)
show variables like "long_query_time"? -- 

除了sql的方式狈醉,我們也可以在配置文件(my.ini)中修改廉油,加入配置時(shí)必須要在[mysqld]后面加入

-- 開啟日志?
slow_query_log = on -- 
-- 記錄日志的log文件(注意:window上必須寫絕對(duì)路徑)
slow_query_log_file = D:/mysql5.5.16/data/show-slow.log-- 
-- 最長(zhǎng)查詢的秒數(shù)?
long_query_time = 2 -- 
-- 表示記錄沒(méi)有使用索引的查詢
log-queries-not-using-indexes -- 

開啟慢查詢會(huì)帶來(lái)CPU損耗與日志記錄的IO開銷,所以建議間斷性的打開慢查詢?nèi)罩緛?lái)觀察MySQL運(yùn)行狀態(tài)

慢查詢分析示例

假設(shè)我們有一條SQL

SELECT * FROM `emp` where ename like '%mQspyv%'? 

執(zhí)行時(shí)間為1.163s苗傅,而我們?cè)O(shè)置的慢查詢時(shí)間為1s抒线,這時(shí)我們可以打開慢查詢?nèi)罩具M(jìn)行日志分析:

# Time: 150530 15:30:58 -- -- 該查詢發(fā)生在2015-5-30 15:30:58
# User@Host: root[root] @ localhost [127.0.0.1] -- --是誰(shuí),在什么主機(jī)上發(fā)生的查詢
# Query_time: 1.134065 Lock_time: 0.000000 Rows_sent: 8 Rows_examined: 4000000 Query_time: --查詢總共用了多少時(shí)間,Lock_time: 在查詢時(shí)鎖定表的時(shí)間,Rows_sent: 返回多少rows數(shù)據(jù),Rows_examined: 表掃描了400W行數(shù)據(jù)才得到的結(jié)果?

如果我們的慢SQL很多,人工分析肯定分析不過(guò)來(lái)渣慕,這時(shí)候我們就需要借助一些分析工具嘶炭,MySQL自帶了一個(gè)慢查詢分析工具mysqldumpslow,以下是常見使用示例

mysqldumpslow -s c -t 10 /var/run/mysqld/mysqld-slow.log # 取出使用最多的10條慢查詢
mysqldumpslow -s t -t 3 /var/run/mysqld/mysqld-slow.log # 取出查詢時(shí)間最慢的3條慢查詢
mysqldumpslow -s t -t 10 -g “l(fā)eft join” /database/mysql/slow-log #得到按照時(shí)間排序的前10條里面含有左連接的查詢語(yǔ)句
mysqldumpslow -s r -t 10 -g 'left join' /var/run/mysqld/mysqldslow.log # 按照掃描行數(shù)最多的

SQL語(yǔ)句常見優(yōu)化

只要簡(jiǎn)單了解過(guò)MySQL內(nèi)部?jī)?yōu)化機(jī)制逊桦,就很容易寫出高性能的SQL

1.不使用子查詢:

SELECT * FROM t1 WHERE id (SELECT id FROM t2 WHERE name='hechunyang')?

在MySQL5.5版本中眨猎,內(nèi)部執(zhí)行計(jì)劃器是先查外表再匹配內(nèi)表,如果外表數(shù)據(jù)量很大强经,查詢速度會(huì)非常慢

在MySQL5.6中睡陪,有對(duì)內(nèi)查詢做了優(yōu)化,優(yōu)化后SQL如下

SELECT t1.* FROM t1 JOIN t2 ON t1.id = t2.id;

但也僅針對(duì)select語(yǔ)句有效匿情,update兰迫、delete子查詢無(wú)效,所以生成環(huán)境不建議使用子查詢

2.避免函數(shù)索引

SELECT * FROM t WHERE YEAR(d) >= 2016;

即使d字段有索引炬称,也會(huì)全盤掃描汁果,應(yīng)該優(yōu)化為:

SELECT * FROM t WHERE d >= '2016-01-01';

3.使用IN替換OR

SELECT * FROM t WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30;

非聚簇索引走了3次,使用IN之后只走一次:

SELECT * FROM t WHERE LOC_IN IN (10,20,30);

4.LIKE雙百分號(hào)無(wú)法使用到索引

SELECT * FROM t WHERE name LIKE '%de%';

應(yīng)優(yōu)化為右模糊

SELECT * FROM t WHERE name LIKE 'de%';

5.增加LIMIT M,N 限制讀取的條數(shù)

6.避免數(shù)據(jù)類型不一致

SELECT * FROM t WHERE id = '19';

應(yīng)優(yōu)化為

SELECT * FROM t WHERE id = 19;

7.分組統(tǒng)計(jì)時(shí)可以禁止排序

SELECT goods_id,count(*) FROM t GROUP BY goods_id;

默認(rèn)情況下MySQL會(huì)對(duì)所有GROUP BY co1玲躯,col2 …的字段進(jìn)行排序据德,我們可以對(duì)其使用ORDER BY NULL禁止排序鲸伴,避免排序消耗資源

SELECT goods_id,count(*) FROM t GROUP BY goods_id ORDER BY NULL;

8.去除不必要的ORDER BY語(yǔ)句

總結(jié)

總的來(lái)說(shuō),我們知道曼查詢的SQL后晋控,優(yōu)化方案可以做如下嘗試:

  • SQL語(yǔ)句優(yōu)化汞窗,盡量精簡(jiǎn),去除非必要語(yǔ)句
  • 索引優(yōu)化赡译,讓所有SQL都能夠走索引
  • 如果是表的瓶頸問(wèn)題仲吏,則分表,單表數(shù)據(jù)量維持在1000W以內(nèi)
  • 如果是單庫(kù)瓶頸問(wèn)題蝌焚,則分庫(kù)裹唆,讀寫分離
  • 如果是物理機(jī)器性能問(wèn)題,則分多個(gè)數(shù)據(jù)庫(kù)節(jié)點(diǎn)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末只洒,一起剝皮案震驚了整個(gè)濱河市许帐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毕谴,老刑警劉巖成畦,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異涝开,居然都是意外死亡循帐,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門舀武,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)拄养,“玉大人,你說(shuō)我怎么就攤上這事银舱”衲洌” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵寻馏,是天一觀的道長(zhǎng)棋弥。 經(jīng)常有香客問(wèn)我,道長(zhǎng)操软,這世上最難降的妖魔是什么嘁锯? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮聂薪,結(jié)果婚禮上家乘,老公的妹妹穿的比我還像新娘。我一直安慰自己藏澳,他們只是感情好仁锯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著翔悠,像睡著了一般业崖。 火紅的嫁衣襯著肌膚如雪野芒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天双炕,我揣著相機(jī)與錄音狞悲,去河邊找鬼。 笑死妇斤,一個(gè)胖子當(dāng)著我的面吹牛摇锋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播站超,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼荸恕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了死相?” 一聲冷哼從身側(cè)響起融求,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎算撮,沒(méi)想到半個(gè)月后生宛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡钮惠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年茅糜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片素挽。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖狸驳,靈堂內(nèi)的尸體忽然破棺而出预明,到底是詐尸還是另有隱情,我是刑警寧澤耙箍,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布撰糠,位于F島的核電站,受9級(jí)特大地震影響辩昆,放射性物質(zhì)發(fā)生泄漏阅酪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一汁针、第九天 我趴在偏房一處隱蔽的房頂上張望术辐。 院中可真熱鬧,春花似錦施无、人聲如沸辉词。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瑞躺。三九已至敷搪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間幢哨,已是汗流浹背赡勘。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捞镰,地道東北人狮含。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像曼振,于是被迫代替她去往敵國(guó)和親几迄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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