MySQL 執行過程與查詢緩存

我的博客地址:http://www.xixinice.commysql

MySQL執行一個查詢過程:
當咱們向MySQL發送一個請求的時候,MySQL到底作了什麼:sql

圖片描述

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 或者其餘相似的解決方案。

ps:文章參考《高性能MySQL》一書

相關文章
相關標籤/搜索