1. 程式人生 > 實用技巧 >MySQL查詢快取

MySQL查詢快取

一.什麼是MySQL查詢快取

  用於儲存MySQL查詢語句返回的完整結果,被命中時,MySQL會立即返回結果,省去解析、優化和執行等操作。把select語句本身做hash計算,計算的結果作為key,查詢結果作為value,如果查詢語句被快取命中,就直接將value返回。   查詢語句中有一些不確定資料時,不會快取;例如now(),current_time();一般來說,如果查詢中包含使用者自定義函式、儲存函式、使用者變數、臨時表、mysql庫中系統表、或者任何包含許可權的表,一般都不會快取。

二.快取會帶來額外開銷

  1>.每個查詢都會先檢查是否命中;   2>.查詢結果要先快取;
  當伺服器有多顆CPU時,且併發量的非常大時,這個時候我們就要考慮各個CPU掙奪快取的記憶體空間的問題,也就是說當這種情況出現時,我們需要去衡量快取的效率問題。當然你還要結合以上兩點進行判斷:

三.查詢快取相關變數

mysql> show global variables like 'query%';
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| query_alloc_block_size       | 8192
| | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 1048576 | | query_cache_type | OFF | | query_cache_wlock_invalidate | OFF | | query_prealloc_size | 8192 | +------------------------------+---------+ 7
rows in set (0.00 sec) 1>.query_cache_type: 查詢快取型別;是否開啟快取功能,開啟方式有三種{ON|OFF|DEMAND},其中DEMAND意味著select語句明確使用sql_cache選項才會快取喲。 2>.query_cache_size: 快取使用的總空間。單位為位元組,大小必須為1024的整數倍。mysql啟動時,會一次分配並立即初始化這裡指定大小的記憶體空間;這意味著, 如果修改此大小,會清空所有快取並重新初始化的。因此不建議修改此大小,最好是一開始就設計好,此記憶體不宜過大。 3>.query_cache_min_res_unit: 儲存快取的最小記憶體塊 (query_cache_size-Qcache_free_memory)/Qcache_queries_in_cache能夠獲得一個理想的值 4>.query_cache_limit: 單個快取物件的最大值,超出時則不予快取;手動使用SQL_NO_CACHE可以人為的避免嘗試快取返回超出此引數限定值得語句 5>.query_cache_wlock_invalidate: 如果某個表被其他使用者連線鎖住了,是否仍然從快取中返回結果,OFF表示返回

四.如何判斷命中率

  MySQL查詢快取的命中率分為次數和位元組命中率。狀態變數是MySQL統計查詢的結果,伺服器變數是我們可以提前設定的值,可以提前定義它的工作屬性,mysql狀態變數是在工作時不斷的統計資料的值(比如快取命中的頻率等等)。我們可以通過以下命令進行查詢:
mysql> show global status like 'Qcache%';
+-------------------------+---------+
| Variable_name           | Value   |
+-------------------------+---------+
| Qcache_free_blocks      | 1       |
| Qcache_free_memory      | 1031352 |
| Qcache_hits             | 0       |
| Qcache_inserts          | 0       |
| Qcache_lowmem_prunes    | 0       |
| Qcache_not_cached       | 125     |
| Qcache_queries_in_cache | 0       |
| Qcache_total_blocks     | 1       |
+-------------------------+---------+
8 rows in set (0.00 sec)
 mysql> 
 1>.Qcache_free_blocks          #指的是空閒塊數,指的是系統分配給MySQL程序的快取總大小空間中還沒有使用的空間。
 2>.Qcache_hits                #指的是命中次數 
 3>.Qcache_inserts            #向快取空間中插入的快取的次數
 4>.Qcache_free_memory          #空閒空間,指的是還沒有被作業系統分配出去的記憶體空間。
 5>.Qcache_lowmem_prunes        #記憶體太小,修剪記憶體的次數
 6>.Qcache_not_cached          #沒被快取的個數
 7>.Qcache_queries_in_cache     #快取中快取的查詢個數
 8>.Qcache_total_blocks         #總塊數,指的是系統分配給MySQL程序的快取總大小空間
 9>.補充知識:
 a>.flush query_cache           #碎片整理
 b>.reset query_cache           #清空快取

五.計算命中率

mysql> show global status where Variable_name='Qcache_hits' OR Variable_name='Com_Select';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select    | 138   |
| Qcache_hits   | 0     |
+---------------+-------+
2 rows in set (0.00 sec)

1>.總共查詢了Com_select 次數,我們這裡是138次;
2>.快取命中了Qcache_hits次數,我們這裡是命中了0次;
  因此我們可以計算次數的命中率:   Qcache_hits/(Qcache_hits+Com_Select),當然這只是次數的命中率,我們想要查詢位元組的命中率的方法就很困難了。因此,也可以參考另外一個指標,命中和寫入的比率,即Qcache_hits/Qcache_inserts的值,此比值如果能大於3:1.則表明快取也是有效的,能達到10:1,為比較理想的情況。如果不能達到這個引數,建議是關閉快取。

六.快取優化思路

  1>.批量寫入,而非多次單個寫入   2>.快取空間不宜過大,因為大量快取同事失效時會導致伺服器假死   3>.必要時,使用sql_CACHE和sql_no_cache手動控制快取。   4>.對寫密集型的應用場景來說,禁用快取反而提高效能。