最近經常有人問我 MySQL Query Cache 相關的問題,就整理一點 MySQL Query Cache 的内容,以供參考。
顧名思義,MySQL Query Cache 就是用來緩存和 Query 相關的資料的。具體來說,Query Cache 緩存了我們用戶端送出給 MySQL 的 SELECT 語句以及該語句的結果集。大概來講,就是将 SELECT 語句和語句的結果做了一個 HASH 映射關系然後儲存在一定的記憶體區域中。
在大部分的 MySQL 分發版本中,Query Cache 功能預設都是打開的,我們可以通過調整 MySQL Server 的參數選項打開該功能。主要由以下5個參數構成:
query_cache_limit:允許 Cache 的單條 Query 結果集的最大容量,預設是1MB,超過此參數設定的 Query 結果集将不會被 Cache
query_cache_min_res_unit:設定 Query Cache 中每次配置設定記憶體的最小空間大小,也就是每個 Query 的 Cache 最小占用的記憶體空間大小
query_cache_size:設定 Query Cache 所使用的記憶體大小,預設值為0,大小必須是1024的整數倍,如果不是整數倍,MySQL 會自動調整降低最小量以達到1024的倍數
query_cache_type:控制 Query Cache 功能的開關,可以設定為0(OFF),1(ON)和2(DEMAND)三種,意義分别如下:
0(OFF):關閉 Query Cache 功能,任何情況下都不會使用 Query Cache
1(ON):開啟 Query Cache 功能,但是當 SELECT 語句中使用的 SQL_NO_CACHE 提示後,将不使用Query Cache
2(DEMAND):開啟 Query Cache 功能,但是隻有當 SELECT 語句中使用了 SQL_CACHE 提示後,才使用 Query Cache
query_cache_wlock_invalidate:控制當有寫鎖定發生在表上的時刻是否先失效該表相關的 Query Cache,如果設定為 1(TRUE),則在寫鎖定的同時将失效該表相關的所有 Query Cache,如果設定為0(FALSE)則在鎖定時刻仍然允許讀取該表相關的 Query Cache。
Query Cache 如何處理子查詢的?
這是我遇到的最為常見的一個問題。其實 Query Cache 是以用戶端請求送出的 Query 為對象來處理的,隻要用戶端請求的是一個 Query,無論這個 Query 是一個簡單的單表查詢還是多表 Join,亦或者是帶有子查詢的複雜 SQL,都被當作成一個 Query,不會被分拆成多個 Query 來進行 Cache。是以,存在子查詢的複雜 Query 也隻會産生一個Cache對象,子查詢不會産生單獨的Cache内容。UNION[ALL] 類型的語句也同樣如此。
Query Cache 是以 block 的方式存儲的資料塊嗎?
不是,Query Cache 中緩存的内容僅僅隻包含該 Query 所需要的結果資料,是結果集。當然,并不僅僅隻是結果資料,還包含與該結果相關的其他資訊,比如産生該 Cache 的用戶端連接配接的字元集,資料的字元集,用戶端連接配接的 Default Database等。
Query Cache 為什麼效率會非常高,即使所有資料都可以 Cache 進記憶體的情況下,有些時候也不如使用 Query Cache 的效率高?
Query Cache 的查找,是在 MySQL 接受到用戶端請求後在對 Query 進行權限驗證之後,SQL 解析之前。也就是說,當 MySQL 接受到用戶端的SQL後,僅僅隻需要對其進行相應的權限驗證後就會通過 Query Cache 來查找結果,甚至都不需要經過 Optimizer 子產品進行執行計劃的分析優化,更不許要發生任何存儲引擎的互動,減少了大量的磁盤 IO 和 CPU 運算,是以效率非常高。
用戶端送出的 SQL 語句大小寫對 Query Cache 有影響嗎?
有,由于 Query Cache 在記憶體中是以 HASH 結構來進行映射,HASH 算法基礎就是組成 SQL 語句的字元,是以必須要整個 SQL 語句在字元級别完全一緻,才能在 Query Cache 中命中,即使多一個空格也不行。
一個 SQL 語句在 Query Cache 中的内容,在什麼情況下會失效?
為了保證 Query Cache 中的内容與是實際資料絕對一緻,當表中的資料有任何變化,包括新增,修改,删除等,都會使所有引用到該表的 SQL 的 Query Cache 失效。
為什麼我的系統在開啟了 Query Cache 之後整體性能反而下降了?
當開啟了 Query Cache 之後,尤其是當我們的 query_cache_type 參數設定為 1 以後,MySQL 會對每個 SELECT 語句都進行 Query Cache 查找,查找操作雖然比較簡單,但仍然也是要消耗一些 CPU 運算資源的。而由于 Query Cache 的失效機制的特性,可能由于表上的資料變化比較頻繁,大量的 Query Cache 頻繁的被失效,是以 Query Cache 的命中率就可能比較低下。是以有些場景下,Query Cache 不僅不能提高效率,反而可能造成負面影響。
如何确認一個系統的 Query Cache 的運作是否健康,命中率如何,設定量是否足夠?
MySQL 提供了一系列的 Global Status 來記錄 Query Cache 的目前狀态,具體如下:
Qcache_free_blocks:目前還處于空閑狀态的 Query Cache 中記憶體 Block 數目
Qcache_free_memory:目前還處于空閑狀态的 Query Cache 記憶體總量
Qcache_hits:Query Cache 命中次數
Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次數,也就是沒有命中的次數
Qcache_lowmem_prunes:當 Query Cache 記憶體容量不夠,需要從中删除老的 Query Cache 以給新的 Cache 對象使用的次數
Qcache_not_cached:沒有被 Cache 的 SQL 數,包括無法被 Cache 的 SQL 以及由于 query_cache_type 設定的不會被 Cache 的 SQL
Qcache_queries_in_cache:目前在 Query Cache 中的 SQL 數量
Qcache_total_blocks:Query Cache 中總的 Block 數量
可以根據這幾個狀态計算出 Cache 命中率,計算出 Query Cache 大小設定是否足夠,總的來說,我個人不建議将 Query Cache 的大小設定超過256MB,這也是業界比較常用的做法。
MySQL Cluster 是否可以使用 Query Cache?
其實在我們的生産環境中也沒有使用 MySQL Cluster,是以我也沒有在 MySQL Cluster 環境中使用 Query Cache 的實際經驗,隻是 MySQL 文檔中說明确實可以在 MySQL Cluster 中使用 Query Cache。從 MySQL Cluster 的原理來分析,也覺得應該可以使用,畢竟 SQL 節點和資料節點比較獨立,各司其職,隻是 Cache 的失效機制會要稍微複雜一點。
<b>聲明:如有轉載本博文章,請注明出處。您的支援是我的動力!文章部分内容來自網際網路,本人不負任何法律責任。</b>
本文轉自bourneli部落格園部落格,原文連結:http://www.cnblogs.com/bourneli/articles/2656196.html,如需轉載請自行聯系原作者