首頁  >  文章  >  資料庫  >  MySQL執行過程以及查詢快取的詳細介紹

MySQL執行過程以及查詢快取的詳細介紹

不言
不言轉載
2019-04-02 16:36:453074瀏覽

這篇文章帶給大家的內容是關於MySQL執行過程以及查詢快取的詳細介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

MySQL執行一個查詢流程:
當我們向MySQL發送一個請求的時候,MySQL到底做了什麼:

MySQL執行過程以及查詢快取的詳細介紹

1.客戶端發送一則查詢給伺服器
2.伺服器先檢查查詢快取,如果命中了快取,則立刻傳回儲存在快取中的結果。否則進入下一階段。
3.伺服器端進行SQL解析、預處理,再由最佳化器產生對應的執行計畫。
4.MySQL根據最佳化器產生的執行計畫,呼叫儲存引擎的API來執行查詢
5.將結果傳回給客戶端。

mysql 主要是由 server 層和儲存層兩部分構成的。
server 層主要包括連接器、查詢緩存,分析器、最佳化器、執行器。
儲存層主要是用來儲存和查詢資料的,常用的儲存引擎有InnoDB、MyISAM,

(1) MySQL客戶端/伺服器通訊協定

MySQL客戶端和伺服器之的通訊協定是「半雙工」的,這就意味著,在任何一個時刻,要么是由伺服器向客戶端發送資料,要麼是由客戶端向伺服器發送資料,這兩個動作不能同時發生。所以我們無法也無須將一個訊息切成小塊獨立來發送。

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

(2).連接器

MySQL客戶端與服務端建立連線,取得目前連線使用者的權限

(3)查詢快取
在解析一個查詢語句之前,如果查詢快取是開啟的,MySQL會檢查這個緩存,是否命中查詢快取中的資料。這個檢查是透過一個大小寫敏感的哈希查找來實現的。
查詢和快取中的查詢即使只有一個位元組不同,那也不會匹配快取結果,這種情況下查詢
就會進入下一階段的處理。

如果目前的查詢剛好命中了查詢快取,那麼在傳回查詢結果之前 MySQL會檢查一次用
戶權限。這仍然是無須解析查詢SQL語句的,因為在查詢快取中已經存放了當前查詢需
要存取的表格資訊。如果權限沒有問題, MySQL會跳過所有其他階段,直接從快取中拿
到結果並回傳給客戶端。這種情況下,查詢不會被解析,不用生成執行計劃,不會被執行.

ps:注意在mysql8 後已經沒有查詢緩存這個功能了,因為這個緩存非常容易被清空掉,命中率比較低。

(3).分析器

既然沒有查到緩存,就需要開始執行 sql 語句了,在執行之前肯定需要先對 sql 語句進行解析。
分析器主要對sql 語句進行語法和語意分析,檢查單字是否拼字錯誤,還有檢查要查詢的表格或欄位是否存在

(4)查詢最佳化

查詢的生命週期的下一步是將一個SQL轉換成一個執行計畫, MySQL再依照這個執行
計畫和儲存引擎進行互動。這包括多個子階段:解析SQL、預處理、最佳化SQ執行計劃。
這個過程中任何錯誤(例如語法錯誤)都可能終止查詢。

2.關於查詢快取

(1)
MySQL 判斷快取命中的方法很簡單:快取存放在一個引用表中,透過一個雜湊值來引用。
MySOL查詢快取保存查詢傳回的完整結果。當查詢命中該快取, MySQL會立刻返回結果跳過了解析,優化和執行階段

查詢快取系統會追蹤查迫中涉及的每個表​​,如果這些表發生變化,那麼和這個表相關的存資料都會失效。

這種機制效率看起來比較低,因為資料表變化時很有可能對查詢結果並沒有變更,但是這種簡單實現代價很小,而這點對於一個非常繁忙的系統來說非常重要。

查詢快取系統對應用程式是完全透明的。應用程式無須關心 MySQL是透過查詢快取傳回的結果還是實際執行傳回的結果。事實上,這兩種方式執行的結果是完全相同的。換句話說,查詢快取無須使用任何語法。無論是 MYSQL開啟成關閉查詢緩在,對應用程式都是透明的。

(2)判斷快取命中

當判斷快取是否命中時, MySQL不會解析、「正規化」或參數化查詢語句,而是直接使用SQL語句和客戶端發送過來的其他原始資訊,在字元上不同,例如空格、註釋,在何的不同,都會導致快取的不中。

當查詢語句中有一些不確定的資料時,則不會被緩存,例如包含函數NOW()或CURRENT_DATE()
的查詢不會被快取.

誤解:
我們常聽到:「如果查詢中包含一個不確定的函數, MySQL則不會檢查查詢快取」。這個說法是不正確的。

因為檢查查詢快取的時候,還沒有解析SQL語句,所以MySQL並不知道查詢語句中是否包含這類函數。

在檢查查詢快取之前, MySQL只做一件事情,就是透過一個大小寫不敏感的檢查看看SQL語句是不是以5EL開頭。

準確的說法應該是:「如果查詢語句中包含任何的不確定函數,那麼在查詢快取中是不可能找到快取結果的」。

注意點:
MySQL的查詢快取在很多時候可以提升查詢效能,在使用的時候,有一些問題需要特別注意。首先,開啟查詢快取對讀取和寫入操作都會帶來額外的消耗:

1.讀取查詢在開始之前必須先檢查是否命中快取
2.如果這個讀取查詢可以被快取,那麼當完成執行後, MySQL若發現查詢快取中沒有這個查詢,會將其結果存入查詢快取,這會帶來額外的系統消耗。
3.這對寫入操作也會有影響,因為當向某個表寫入資料的時候, MySQL必須將對應表的所有快取都設定失效。如果查詢快取非常大或碎片很多,這個操作就可能會帶來大系統消耗(設定了很多的記憶體給查詢快取用的時候)

如果查詢快取使用了很大量的記憶體,快取失效操作就可能成為一個非常嚴重的問題瓶頸
如果快取中存放了大量的查詢結果,那麼快取失效操作時整個系統都可能會僵死一會

因為這個操作是靠一個全域鎖操作保護的,所有需要做該操作的查詢都要等待這個鎖,
而且無論是檢測是否命中緩存、還是緩存失效檢測都需要等待這個全域鎖。

(3)什麼情況下查詢快取能發揮作用
理論上,可以透過觀察開啟或關閉查詢快取時候的系統效率來決定是否需要開啟查詢。

對手那些需要消耗大量資源的查詢通常都是非常適合快取的。
例如一些總結計算查詢具體的如 COUNT()等。總地來說,對於複雜的SELECT語句都可以使用查詢快取,
例如多表JOIN後還需要做排序和分頁,這類查詢每次執行消耗都很大,但是返回的結果集卻很小,非常適合查詢快取。

不過需要注意的是,涉及的表上 UPDATE、 DELETE和 INSERT操作相比 SELECT來說要非常少才行。

判斷查詢快取是否有效的直接資料是命中率。就是使用查詢快取傳回結果佔總查詢的比率

不過快取中率是一個很難判斷的數值。命中率多大才是好的命中率。具體情況,具體分析。

只要查詢快取帶來的效率提升大於查詢快取帶來的額外消耗,即使30%命中率對系統效能提升也有很大好處。另外,快取了哪些查詢也很重要,例如,被快取的查詢本身消耗非常巨大,那麼即使快取命中率非常低,也仍然會對系統效能提升有好處

快取未命中可能有如下幾個原因:

1.查詢語句無法被快取,可能是因為查詢中包含一個不確定的函數(如CURREN_DATE)或查詢結果太大而無法快取。這都會導致狀態值 Cache not cached增加。
2.MySQL從未處理這個查詢,所以結果也從不曾被快取過。

3.還有一種情況是雖然之前緩存了查詢結果,但是由於查詢緩存的內存用完了,MySQL需要將某些緩存“逐出”,或者由於數據表被修改導致緩存失效。

如果你的伺服器上有大量快取未命中,但是實際上絕大數查詢都被快取了,那麼一定是有如下情況發生:

1.查詢快取還沒完成預熱。也就是說, MySQL還沒有機會將查詢結果都快取起來。
2.查詢語句之前從未執行過。如果你的應用程式不會重複執行一條查詢語句,那麼即使完成預熱仍然會有很多快取未命中
3.快取失效操作太多了。

(4)如何設定 和維護查詢快取

query_cache_type

是否開啟查詢快取。可以設定成0FN或 DEMAND。 DEMAND表示只有在查詢語句中明確寫明SQL_ CACHE的語句才會放入查詢快取。這個變數可以是會話層級的也可以是全域層級的

query_cache_size

查詢快取所使用的總記憶體空間,單位是位元組。這個值必須是1024的整數倍,否則 MySQL實際分配的資料會和你指定的略有不同。

query_cahce_min_res_unit

#在查詢快取中分配記憶體區塊時的最小單位。

query_chache_limit

##

MySQL能够缓存的最大査询结果。如果查询结果大于这个值,则不会被缓存。因为査询缓存在数据生成的时候就开始尝试缓存数据,所以只有当结果全部返回后,才知道查询结果是否超出限制

如果超出, MySQL则增加状态值 Cache_not_cached,并将结果从查询缓存中删除如果你事先知道有很多这样的情况发生,那么建议在查询语句中加入

(5)替代方案

MySQL查询缓存工作的原则是:执行查询最快的方式就是不去执行,但是查询仍然需要发送到服务器端,服务器也还需要做一点点工作。如果对于某些查询完全不需要与服务器通信效果会如何呢?这时客户端的缓存可以很大程度上帮你分担 MySQL服务器的压力

总结:

完全相同的查询在重复执行的时候,查询缓存可以立即返回结果,而无须在数据库中重新执行一次。根据我们的经验,在高并发压力环境中在询缓存会导致系统性能的下降,甚至僵死。

如果一定要使用查询缓存,那么不要设置太大内存,而且只有在确收益的时候才使用。

那该如何判断是否应该使用查询缓存呢?建议使Percona server.,观察更细致的日志,并做一些简单的计算。还可以查看缓存命中率(并不总是有用)、“ NSERTS和 SELECT比率”(这个参数也并不直观)、或者“命中和写入比率”(这个参考意义较大)。

查询缓存是一个非常方便的缓存,对应用程序完全透明,无须任何额外的编码,但是、如果希望有更高的缓存效率,我们建议使cache 或者其他类似的解决方案。

【相关推荐:MySQL视频教程

以上是MySQL執行過程以及查詢快取的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除