MySQL源碼學(xué)習(xí):關(guān)于慢查詢?nèi)罩局械腞ows_examined=0 |
發(fā)布時(shí)間: 2012/8/24 17:14:35 |
最近在一個(gè)項(xiàng)目中DBA同學(xué)問(wèn)了一個(gè)問(wèn)題:為什么很多慢查詢?nèi)罩局酗@示 Rows_examined : 0? 需要說(shuō)明的是, 這類慢查詢語(yǔ)句都是類似 select count(*) from (…)t; 在說(shuō)明這個(gè)問(wèn)題之前,我們先指出兩個(gè)相關(guān)背景: 1、MySQL的臨時(shí)表,都是MyISAM的。 2、MyISAM表中的記錄總數(shù)是額外存儲(chǔ)的,count(*)的時(shí)候不需要遍歷數(shù)據(jù)。 3、把count(*)轉(zhuǎn)換為取一個(gè)const值這件事情,是在優(yōu)化(optimize)階段作的。 問(wèn)題分析: 這個(gè)值對(duì)應(yīng)于代碼中的examined_row_count,用于統(tǒng)計(jì)每次執(zhí)行過(guò)程中實(shí)際掃描的記錄數(shù)。 正常的流程: 查詢執(zhí)行過(guò)程中,每個(gè)子查詢的信息都在curr_join,其中curr_join->examined_rows在每次掃一行的時(shí)候++.子查詢完成后,curr_join->examined_rows累積到examined_row_count中。 哪里清0的? 我們上面這個(gè)語(yǔ)句,from內(nèi)的子查詢,curr_join->examined_rows是正常的,但在外部計(jì)算count的時(shí)候,上面提到的優(yōu)化結(jié)果認(rèn)為這個(gè)階段是不需要掃描表的,把thd->examined_row_count給置0了。罪魁代碼在JOIN::exec()中。 從代碼中的注釋來(lái)看,似乎是一個(gè)沒(méi)有考慮細(xì)致的地方,待求證。
改進(jìn)分析: 縱然有很多理由,在慢查詢?nèi)罩局酗@示的0還是不友好的,可以理解為是一個(gè)bug。 實(shí)際上從上面的分析可知,如果是復(fù)合查詢中的一個(gè)環(huán)節(jié),尤其不是第一個(gè)環(huán)節(jié),此處清0會(huì)使顯示結(jié)果出錯(cuò)。從當(dāng)前的thd信息中可以判斷出是否使用了子查詢,簡(jiǎn)單一點(diǎn)的修改,根據(jù)thd.derived_tables信息來(lái)確定是否清0。 實(shí)際上每次執(zhí)行開始之前的這個(gè)值是被reset過(guò)的,有理由懷疑這個(gè)地方實(shí)際上可以直接刪除這句話。這個(gè)比較激進(jìn),要求證一下。 簡(jiǎn)單驗(yàn)證: 加了thd.derived_tables判斷后,
方便調(diào)試起見,把所有的查詢都打到slow_log了。 本文出自:億恩科技【mszdt.com】 服務(wù)器租用/服務(wù)器托管中國(guó)五強(qiáng)!虛擬主機(jī)域名注冊(cè)頂級(jí)提供商!15年品質(zhì)保障!--億恩科技[ENKJ.COM] |