首頁 >資料庫 >mysql教程 >mysql怎麼運作的

mysql怎麼運作的

(*-*)浩
(*-*)浩原創
2019-05-25 17:57:373918瀏覽

MySQL邏輯架構

MySQL邏輯架構整體分為三層,最上層為客戶層,並非MySQL所獨有,諸如,連接處理、授權認證、安全性等功能均在這一層處理。

MySQL大多數核心服務均在中間這一層,包括查詢解析、分析、最佳化、快取、內建函數(時間、數學、加密等),所有的跨儲存引擎的功能也在這一層實作:預存程序、觸發器、視圖等。

最下層為儲存引擎,其負責MySQL中的資料儲存和擷取,中間的服務層透過API與儲存引擎通信,這些API介面屏蔽了不同儲存引擎的差異。

mysql怎麼運作的

MySQL查詢流程

#當向MySQL傳送一個要求的時候:

mysql怎麼運作的

1.客戶端/服務端通訊協定

MySQL客戶端/服務端通訊協定是「半雙工」的:在任何時刻,要麼是伺服器向客戶端發送數據,要么是客戶端向伺服器發送數據,這兩個動作不能同時發生。一旦一端開始發送訊息,另一端要接受完整個訊息才能回應它,所以我們無法也無須將一個訊息切成小塊獨立發送,也沒有辦法進行流量控制。

客戶端用一個單獨的資料包將查詢請求傳送給伺服器,所以當查詢語句很長的時候,需要設定max_allowed_pa​​cket參數。但是要注意的是,如果查詢實在太大,服務端會拒絕接受更多資料並拋出例外。

與之相反的是,伺服器回應給使用者的資料通常會很多,由多個資料包組成。但是當伺服器回應客戶端請求時,客戶端必須完整的接受整個回傳結果,而不能簡單的只取前面幾個結果,然後讓伺服器停止發送。因而在實際開發中,盡量保持查詢簡單且只返回必需的數據,減小通信間數據包的大小和數量是一個非常好的習慣,這也是查詢中盡量避免使用SELECT * 以及加上LIMIT限制的原因之一。

2.查詢快取

在解析一個查詢語句前,如果查詢快取是開啟的,那麼MySQL會檢查這個查詢語句是否會命中查詢快取中的數據。如果目前查詢恰好命中查詢快取,在檢查一次使用者權限後直接傳回快取中的結果。這種情況下,查詢不會被解析,也不會產生執行計劃,更不會執行。

MySQL將快取存放在一個引用表(類似HashMap的資料結構),透過一個雜湊值索引,這個雜湊值透過查詢本身、目前要查詢的資料庫、客戶端協定版本號等一些可能影響結果的資訊計算得來。所以兩個查詢在任何字元上的不同(空格、註解),都會導致快取不會命中。

如果查詢中包含任何使用者自訂函數、儲存函數、使用者變數、暫存資料表、mysql函式庫中的系統表,其查詢結果都不會被快取。例如函數NOW()或CURRENT_DATE()會因為不同的查詢時間,傳回不同的查詢結果,再例如包含CURRENT_USER或CONNECION_ID()的查詢語句會因為不同的使用者而傳回不同的結果,將這樣的查詢結果快取起來沒有任何的意義。

3.快取失效

MySQL的查詢快取系統會追蹤查詢中涉及的每個表​​,如果這些表(資料或結構)發生變化,那麼和這張表相關的所有快取資料都將失效。正因為如此,在任何的寫入操作時,MySQL必須將對應表的所有快取都設為失效。如果查詢快取非常大或碎片很多,這個操作可能會帶來很大的系統消耗,甚至導致系統僵死一會兒。而且查詢快取對系統的額外消耗也不僅僅在寫入操作,讀取操作也不例外:

1.任何的查詢語句在開始之前都必須經過檢查,即使這條SQL語句永遠不會命中快取

2.如果查詢結果可以被緩存,那麼執行完成後,會將結果存入緩存,也會帶來額外的系統消耗

基於此,要知道並不是什麼情況下查詢快取都會提高系統效能,快取和失效都會帶來額外消耗,只有當快取帶來的資源節約大於本身消耗的資源時,才會為系統帶來效能提升。但要如何評估開啟快取是否能帶來效能提升是一件非常困難的事情,。如果系統確實存在一些效能問題,可以嘗試開啟查詢緩存,並在資料庫設計上做一些最佳化:例如:

#1.用多個小表取代一個大表,注意不要過度設計

2.批次插入取代循環單一插入

3.合理控制快取空間大小,一般來說其大小設定為數十兆比較適合

4.可以透過SQL_CACHE和SQL_NO_CACHE來控制某個查詢語句是否需要進行快取

不要輕易開啟查詢緩存,特別是寫入密集型應用。如果實在是忍不住,可以將query_cache_type 設為DEMAND,這時只有加入SQL_CACH的查詢才會走緩存,其他查詢則不會,這樣可以非常自由地控制哪些查詢需要被緩存。

4.語法解析與預處理

 MySQL透過關鍵字將SQL語句解析,並產生一顆對應的解析樹。這個過程解析器主要透過語法規則來驗證和解析。例如SQL中是否使用了錯誤的關鍵字或是關鍵字的順序是否正確等等。預處理則會根據MySQL規則進一步檢查解析樹是否合法。例如檢查要查詢的資料表和資料列是否存在等等。

5.查詢最佳化

語法樹被認為是合法之後,並且有優化器將其轉換成查詢計劃,多數情況下,一條查詢可以有很多種執行方式,最後都會回傳對應的結果,而優化器的作用就是找到這其中最好的執行計畫。

MySQL的查詢最佳化器是一個非常複雜的元件,它使用了非常多的最佳化策略來產生一個最優的執行計劃:

1.重新定義表的關聯順序(多張表關聯查詢時,不一定會依照SQL中指定的順序進行,但有一些技巧可以指定關聯順序)

#2.最佳化MIN()和MAX()函數(找某列的最小值,如果該列有索引,只需要查找B Tree索引最左端,反之則可以找到最大值)

#3.提前終止查詢(使用Limit時,查找到滿足數量的結果集後會立即終止查詢)

4.最佳化排序(在舊版MySQL會使用兩次傳輸排序,即先讀取行指標和需要排序的欄位在記憶體中對其排序,然後再根據排序結果去讀取資料行,而新版本採用的是單次傳輸排序,也就是一次讀取所有的資料行,然後根據給定的列排序)

6.查詢執行引擎

在完成解析和最佳化階段以後,MySQL會產生對應的執行計劃,查詢執行引擎根據執行計劃給出的指令逐步執行得出結果。整個執行過程的大部分操作都是透過呼叫儲存引擎實現的介面來完成,這些介面被稱為handler API。查詢過程中的每一張表由一個handler實例表示,實際上,MySQL在查詢優化階段就為每一張表創建了一個handler實例,優化器可以根據這些實例的接口來獲取表的相關信息,包括表的所​​有列名、索引統計資訊等。儲存引擎介面提供了非常豐富的功能,但其底層僅有幾十個接口,這些接口像塔積木一樣完成了一次查詢的大部分操作。

7.傳回結果給客戶端

查詢執行的最後一個階段就是將結果傳回給客戶端。即使查詢不到數據,MySQL仍然會傳回這個查詢的相關信息,例如該查詢影響到的行數以及執行時間等等。

如果查詢快取被開啟且這個查詢可以被緩存,MySQL也會將結果存放到快取中。

結果集傳回客戶端是一個增量且逐步回傳的過程。有可能MySQL在產生第一條結果時,就開始逐步到客戶端回傳結果集了。這樣服務端就無須儲存太多結果而消耗過多內存,也可以讓客戶端第一時間獲得回傳結果。需要注意的是,結果集中的每一行都會以一個滿足①中所描述的通訊協定的資料包發送,再透過TCP協定進行傳輸,在傳輸過程中,可能對MySQL的資料包進行快取然後批次發送。

MySQL整個查詢執行過程

1.客戶端向MySQL伺服器發送一條查詢請求

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

3.伺服器進行SQL解析、預處理、再由優化器產生對應的執行計劃

4.MySQL根據執行計劃,呼叫儲存引擎的API來執行查詢

以上是mysql怎麼運作的的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn