基本步驟為:
1.客戶端發(fā)送一條查詢給服務(wù)器。
2.服務(wù)器先檢查查詢緩存,如果命中了緩存,則立刻返回存儲在緩存中的結(jié)果。否則進(jìn)入下一階段。
3。服務(wù)器端進(jìn)行SQL解析,預(yù)處理,再由優(yōu)化器生成對應(yīng)的執(zhí)行計劃
4。MySql根據(jù)優(yōu)化器生成的執(zhí)行計劃,調(diào)用存儲引擎的API執(zhí)行查詢。
5。返回結(jié)果給客戶端。
MySQL客戶端/服務(wù)器通信協(xié)議
MySQL客戶端和服務(wù)器之間的通信協(xié)議是“半雙工”的,這意味著,在任何野時刻,要么是由服務(wù)器向客戶端發(fā)送數(shù)據(jù),要么是客戶端向服務(wù)器發(fā)送數(shù)據(jù),這兩個動作不能同時執(zhí)行。所以,我們無法也無須將也消息切成小塊獨(dú)立來發(fā)送。
這種協(xié)議讓MySQL通信簡單快速,但是也從很多地方限制了MySQL。一端開始發(fā)送消息,另一端要接受完整個消息才能響應(yīng)它。這就像來回拋球的游戲:在任何時刻,只有一個人能控制球,而且只有控球的人才能將球發(fā)回去。
相反的,一般服務(wù)器響應(yīng)給用戶的數(shù)據(jù)通常很多,由多個數(shù)據(jù)包組成。當(dāng)服務(wù)器開始響應(yīng)客戶端請求時,客戶端必須完整地接受整個返回結(jié)果,而不能簡單地只去前面這個結(jié)果,然后讓服務(wù)器停止發(fā)送。這就是為什么要加Limit
查詢狀態(tài)
對于一個MySQL連接,或者說一個線程,任何時刻都有一個狀態(tài),該狀態(tài)表示了MySQL當(dāng)前正在做什么,最簡單是使用SHOW FULLPROCESSLIST命令。在一個查詢的生命周期中,狀態(tài)會變化很多次。MySQL官方手冊對這些狀態(tài)值的含義最權(quán)威的解釋:
Sleep:線程等待客戶端發(fā)送新的請求。
Query:線程正在執(zhí)行查詢或者正在將結(jié)果發(fā)送給客戶端。
Locked:線程在等待表鎖。等待行鎖時不會出現(xiàn)。
Analyzing and statistics:線程正在收集存儲引擎統(tǒng)計信息,并生成查詢計劃。
Sorting result:線程正在對結(jié)果排序。
查詢緩存
在解析SQL語句之前,如果查詢緩存是打開的,MySql會首先檢查這個查詢是否命中緩存中的數(shù)據(jù)。如果當(dāng)前的查詢恰好命中了查詢緩存,那么在返回查詢結(jié)果之前MySQL會檢查一次用戶權(quán)限,如果權(quán)限沒問題就會返回,這種情況下查詢不會被解析,不用生成執(zhí)行計劃,不會被執(zhí)行。
查詢優(yōu)化處理
在查詢緩存的下一步是解析SQL,預(yù)處理,優(yōu)化SQL執(zhí)行計劃。這個過程中任何錯誤都可能終止查詢。
語法解析和預(yù)處理
首先MySQL通過關(guān)鍵字將SQL語句進(jìn)行解析,并生成一顆對應(yīng)的”解析樹”。MySQL解析器將使用MySQL語法規(guī)則和解析查詢。
預(yù)處理會根據(jù)MySQL規(guī)則進(jìn)一步檢查解析樹是否合法。
查詢優(yōu)化
如果語法樹是被認(rèn)為是合法的,現(xiàn)在就會通過優(yōu)化器轉(zhuǎn)化為執(zhí)行計劃。
MysQL使用基于成本的優(yōu)化器,它將嘗試預(yù)測一個查詢使用某種執(zhí)行計劃時的成本,并選擇其中成本最小的一個。
有很多原因會導(dǎo)致MySQL優(yōu)化器會選擇錯誤執(zhí)行計劃。
1。統(tǒng)計信息不準(zhǔn)確。
2。執(zhí)行計劃中的成本估算不等同于實(shí)際執(zhí)行的成本。
3。MySQL的最優(yōu)可能和你想的不一樣
4。MySQL不考慮其他并發(fā)執(zhí)行的查詢
MySQL可以支持的優(yōu)化類型:
1。重新定義關(guān)聯(lián)表的順序
2。外連接轉(zhuǎn)換為內(nèi)連接
3。使用等價變換規(guī)則
4。優(yōu)化COUNT(),MIN和MAX()——利用索引優(yōu)化
5。預(yù)估轉(zhuǎn)換為常數(shù)表達(dá)式
6。覆蓋索引掃描
7。子查詢優(yōu)化
8。提前終止查詢–LIMIT
9。等值傳播
10。列表in()的比較–不是簡單的or,將其排序并用二分查找的方式來確定列表中的值是否滿足。