MySQL查詢執行的基礎

2022-07-26 19:51:12 字數 2480 閱讀 5833

當希望mysql能夠以更高的效能執行查詢時,最好的辦法就是弄清楚mysql是如何優化和執行查詢的。一旦理解這一點,很多查詢優化實際上就是遵循一些原則讓優化器能夠按照預想的合理的方式執行。

換句話說,是時候回頭看看我們之前討論的內容了:mysql執行乙個查詢的過程。當向mysql傳送乙個請求的時候,mysql到底做了什麼。

1 客戶端傳送一條查詢給伺服器。

2 伺服器首先檢查快取,如果命中快取,則立即返回儲存在快取的結果,否則進入下一階段。

3 伺服器進行sql解析,預處理,再由優化生成器生成對應的執行計畫。

4 mysql根據優化器生成的執行計畫,呼叫儲存引擎的api來執行查詢。

5 強結果返回給客戶端。

上面的每一步都比想象的負載,我們在後續章節中將繼續討論。我們會看到在每乙個階段查詢出來處於何種狀態。查詢優化器是其中特別複雜也是特別難理解的部分。還有很多例外的情況,例如,當查詢使用繫結變數之後,執行路徑會有所不同,我們將在下一章討論這一點。

一 mysql客戶端/伺服器通訊協議

一般來說,不需要去理解mysql通訊協議的內部實現細節,只需要大致理解通訊協議是如何工作的。mysql客戶端和伺服器之間的通訊協議是「半雙工 」的,這意味著,在任何乙個時刻,要麼是由伺服器向客戶端傳送資料,要麼是由客戶端向伺服器傳送資料,這兩個動作不能同時發生。所以,我們無法也無須將乙個訊息切成小塊來獨立傳送。

這種協議讓mysql通訊簡單快速,但是也從很多地方限制住了mysql。乙個明顯的限制是,這意味著無法進行流量控制。一旦一端開始發生訊息,另一端要接收完整個訊息才能響應它。這就像來回的拋球遊戲:任何時刻只有乙個人能控制球,而且只有控制球的一方才能將球拋回去(傳送訊息)。

客戶端用乙個單獨的資料報將查詢傳給伺服器。這也是為什麼當查詢的語句很長的時候引數max_allowed_packet 就特別重要了。一旦客戶端傳送了請求,它能做的事情,就只是等待結果了。

相反的,一般伺服器響應給客戶的資料通常很多,由多個資料報組成。當伺服器開始響應客戶端請求時,客戶端必須完整的接受整個返回結果,而不能簡單的只取前面幾條結果,然後然伺服器停止傳送資料,這種情況下,客戶端若接收完整的結果,然後取前面幾條需要的結果,或者接收完幾條結果後,就粗暴的斷開連線,都不是好主意。這也是在必要的時候一定要在查詢語句中加上limit限制的原因。

換一種方式解釋這種行為:當客戶端從伺服器取資料時,看起來是乙個資料拉去的過程,但實際上是mysql在向客戶端推送資料的過程。客戶端不斷的接收從伺服器推送的資料,,客戶端也無法讓伺服器停下來。

多數連線mysql的庫函式都可以獲得全部結果集並快取到記憶體裡,還可以逐行獲取需要的資料。預設一般是獲得全部結果集並快取到記憶體中。mysql通常需要等待所有的資料都已經傳送給客戶端,才能釋放這條查詢所佔的資源,所有接受全部結果通常可以減少伺服器壓力,讓查詢能夠早點結束,早點釋放相應的資源。

當使用多數連線mysql的庫函式從mysql獲取資料時,其結果看起來都像是從mysql伺服器獲取的資料,而實際上都是從這個庫函式的緩衝讀取資料。多數情況下這沒什麼問題,但是如果需要返回乙個很大的結果集的時候,這樣走並不好,因為庫函式會花費很多時間和記憶體來儲存所有的結果集。如果能盡早的開始處理這些結果集,就能大大減少記憶體的消耗,這種情況下可以不使用快取記錄結果而是直接處理。這樣走的缺點是,對於伺服器來說,需要查詢完成後才能釋放資源,所以在和客戶端互動的整個過程中,伺服器的資源都是被這個查詢所占用的。

查詢狀態

對於乙個mysql的連線,或者說是乙個執行緒,任何時刻都有乙個狀態,該狀態表示了mysql當前正在做什麼。有很多種方式能檢視當前的狀態,最賤的的是使用show full processlist 命令(該命令返回結果中的command列就表示當前的狀態)。在乙個查詢的生命週期中,轉台會變回很多次。mysql官方收藏對這些狀態值的含義有最權威的解釋,下面將這些狀態列出來,並做乙個簡單的解釋。

sleep

執行緒正在等待客戶端傳送新的請求

query

執行緒正在執行查詢或者正在將結果傳送給客戶端。

locked

在mysql伺服器層,該執行緒正在等待表鎖。在儲存引擎實現的鎖,例如innodb的行鎖,並不會體現在該執行緒狀態中。對於myisam來說這是乙個比較典型的狀態,但在其他沒有行鎖的引擎中也會長出現。

analyzing and statistics

執行緒正在收集儲存引擎的統計資訊,並生成查詢的執行計畫。

copying to tmp table【on disk】

執行緒正在執行查詢,並且將其結果集都複製到乙個臨時表中,這種狀態一般要麼是做group by 操作,要麼是檔案排序操作,或者是union 操作。如果這個狀態後面還有on disk 標記,那麼表示mysql正在將乙個記憶體臨時表放到磁碟上。

sorting result

執行緒正在對結果集進行排序。

sending data

這表示多種情況:執行緒可能是在多個狀態之間傳送資料,或者結果集,或者在向客戶端返回資料。

了解這些狀態的戒備含義非常有用,這可以讓你更快的了解當前誰正在持球。在乙個繁忙的伺服器上,可能會看到大量的不正常狀態,例如statistics 正在占用大量的時間。這通常表示,某個地方有異常了。

MySQL查詢執行的基礎 查詢優化處理

查詢的生命週期的下一步是將乙個sql轉換成乙個可執行計畫,mysql再按照這個計畫和儲存引擎進行互動 預處理器則會根據一些mysql規則進一步檢查解析樹是否合法。它會檢查資料表和資料列是否存在,還會解析名字和別名,看看它們是否存在歧義。當語法樹被認為是合法的時候,將轉由優化器去轉化成執行計畫。一條查...

查詢執行的基礎

mysql的一般查詢流程如下 mysql客戶但和伺服器中間的通訊協議時 半雙工 的。因此當查詢語句較長時引數 max allowed packet 很重要。都是從資料庫中的快取獲取資料。可以通過對mysql的介面,進行設定取消緩衝。mysql的查詢狀態 show full processlist進行...

4 4 查詢執行的基礎

mysql執行乙個查詢的過程,可以用下圖表示 我們可以看到當向mysql傳送乙個請求的時候,mysql究竟做了什麼 1 客戶端傳送一條查詢給伺服器。2 伺服器先檢查查詢快取,如果命中了快取,則立刻返回儲存在快取中的結果。否則進入下乙個階段。3 伺服器端進行sql解析 預處理,再由優化器生成對應的執行...