1. 程式人生 > >MySQL查詢快取 --《高效能MySQL》讀書筆記

MySQL查詢快取 --《高效能MySQL》讀書筆記

        Query Cache(QC)         快取完整的Select結果,當查詢命中該快取,MySQL會立刻返回結果,跳過解析、優化和執行階段。 1、如何判斷快取命中         快取存放在一個引用表中,通過雜湊值引用。雜湊值包括查詢本身、待查資料庫、客戶端協議版本等可能影響返回結果的資訊。 注:
  • 當表被lock tables鎖住時,仍可以通過查詢快取返回資料。
  • 任何字元不同(包括空格、註釋)都會導致快取的不命中。
  • 不會被快取:①查詢語句包含不確定資料(如函式now()、current_date());②不同使用者返回不同結果current_user()、connection_id());③包含自定義函式、儲存函式、使用者變數、臨時表、mysql中的系統表、包含列級別許可權的表等等。
a)“如果查詢中包含一個不確定的函式,MySQL則不會檢查查詢快取”?
    錯誤。MySQL檢查查詢快取時,僅僅檢測SQL語句是否以sel(大小寫不敏感)開頭,還沒有解析SQL語句。 b)“如果查詢語句中包含任何不確定函式,則查詢快取中是找不到快取結果的”     正解。即使執行了,結果也不會放在查詢快取中。     MySQL只要發現不能被快取的部分,將禁止此查詢被快取。 如果查詢中帶有current_date,最好直接寫死'2016-01-25', 缺點:
  • 開啟查詢快取會對讀寫操作帶來額外的消耗;
  • 讀查詢開始前必須檢查是否命中;
  • 如果讀查詢可被快取但還未被快取,會將其結果存入查詢快取(額外消耗);
  • 寫資料時,對應表所有快取都失效,如果查詢快取非常大或碎片很多,將帶來大量系統消耗。
  • 查詢快取加鎖排他。
2、查詢快取如何使用記憶體         查詢快取完全儲存於記憶體中,MySQL自行管理這塊記憶體。
  • 伺服器啟動;
  • 初始化查詢快取所需記憶體;(此記憶體池是一個完整的空閒塊,大小為配置的查詢快取大小減去維護查詢快取資料結構所需空間<約40K>)
  • 查詢結果若需要快取,MySQL從快取池申請一個數據塊用於儲存,該塊大於引數query_cache_min_res_unit,即使查詢結果遠小於query_cache_min_res_unit。【查詢開始返回結果就分配空間,無法預估查詢結果的大小,So無法為每個查詢結果精確分配大小合適的快取空間】
  • 快取時,MySQL優先選擇儘可能小的資料塊,若該塊空間不夠,將申請新的儘可能小的資料塊;(亦可能選擇較大的,此不深究);若該塊有剩餘,MySQL將其釋放,並放入空閒部分。
Note:
  • 分配資料塊需先鎖住空間塊,再找到合適大小,so相對耗時,MySQL儘量避免。
  • 碎片:若平均查詢結果非常小,伺服器併發地向兩個連線返回結果。返回結果後MySQL回收剩餘資料塊時,發現回收的塊小於query_cache_min_res_unit,不能直接在後續的記憶體塊中分配使用,即產生碎片。
如何減少碎片呢?   完全避免是不可能的,選擇合適的query_cache_min_res_unit可平衡每個資料塊的大小和每次儲存結果時記憶體申請的次數。(太小導致頻繁申請,太大導致大量碎片)實際消耗(query_cache_size - Qcache_free_memory)除以Qcache_queries_in_cache計算單各查詢的平均快取大小。最糟糕時,任何兩個資料塊間都有一個非常小的空閒塊,此時Qcache_free_blocks恰好達到Qcache_total_blocks / 2,碎片問題很嚴重。         可通過query_cache_limit限制可快取的最大查詢結果以便減少大查詢結果的快取,從而減少碎片。 3、何時應該使用查詢快取     快取和失效都會帶來額外的消耗,So當快取帶來的資源節約大於其本身的資源消耗才推薦使用。
  • 命中率:Qcache_hits / (Qcache_hits+Com_select)(核心,但難判斷且不直觀)
  • 消耗大量資源的查詢;(如彙總計算count等;多表join再排序分頁,查詢消耗巨大但返回結果集小)
  • 相關表update、delete、insert 比 select少很多;
  • 資料的訪問頻率非常高,或者訪問頻率不高,但是它的生存週期很長。 
  • 命中和寫入比率:Qcache_hits / Qcache_inserts(通常3:1即可,10:1更佳)
如何 分析和配置 查詢快取
show variables like '%query_cache%'; +------------------------------+---------+ | Variable_name                | Value   | +------------------------------+---------+ | have_query_cache             | YES     | | query_cache_limit            | 1048576 | | query_cache_min_res_unit     | 4096    | | query_cache_size             | 599040  | | query_cache_type             | ON      | | query_cache_wlock_invalidate | OFF     | +------------------------------+---------+ (1)query_cache_type有3個值 :   a、0或off,代表關閉   b、1或on,代表開啟  在on模式下,如果你不想使用快取,需要通過sql_no_cache關鍵詞來顯示的指明, 如select sql_no_cache id,name from tableName; c、2 或demand,按需要是否開啟快取。  當sql語句中有SQL_CACHE關鍵詞時才快取, 如:select SQL_CACHE user_name from users where user_id = '100';   無論哪種模式下,當sql中使用了mysql函式時,都不會快取。  (2)query_cache_size表示分配給查詢快取的總記憶體大小,該值並非越大越好,需要結合實際情況設定。 (3)query_cache_limit 單次查詢結果大於這個值,則不再快取。該值預設是1048576,即1M。 (4)query_cache_min_res_unit 分配的最小快取塊大小,預設是4KB,設定該值大,對大資料查詢有好處,但如果你的查詢都是小資料查詢,就容易造成記憶體碎片和浪費。 (5)query_cache_wlock_invaliate  預設為OFF,可以讀取已鎖定的表的快取資料。 快取功效實踐: ①測試資料:MySQL自帶資料庫sakila.rental ②測試SQL: a)SELECTCOUNT(*)FROM sakila.rental; b)SELECT  rental_date FROM sakila.rental WHERE rental_date>'2005-08-20 21:35:58'; 時間對比如下: 耗時分別為:navicat和【黑屏】,黑屏時間保留兩位小數(0.01 s)
耗時ms 開啟快取 (首次執行) 開啟快取 (多次平均) 關閉快取 (首次執行) 關閉快取 (多次平均)
a 36【10】 0【0】 8【30】 3【10】
b 9【10】 1【0】 9【10】 2【0】
Note:
  • 關閉快取後重啟MySQL:net stop/start mysql57
  • 一定要先關閉快取,不能在執行時設定引數關閉。
  • C:\ProgramData\MySQL\MySQL Server 5.7\my.ini檔案:query_cache_type=0,query_cache_size=0
總結:
  • 開啟快取是要消耗資源的;
  • 多次執行相同查詢,開啟快取效果更佳;
疑問:
  • 關閉快取後,首次執行雖比開啟快取節省時間,但依舊比多次平均執行耗時。
  • 執行a語句時,黑屏總比navicat耗時?
關閉快取後,第一次查詢很慢,後面很快?         ①快取禁用了,第一次查時資料從硬碟載入到記憶體,再連續查速度變快。 由於記憶體有限,一會兒後資料從記憶體清除,當然再查就慢了。         ②禁用快取,僅是禁止了SQL語句重新分析和資料讀取,但如果有些表,索引已經開啟或者載入到記憶體中,則在記憶體無其它衝突請求時仍然有效。 因此會速度快於第一次。 常用命令:
  • 碎片整理:flush query cache【將所有查詢快取重新排序,並將所有空閒空間聚集起來】
  • 清空快取:reset query cache【加鎖訪問所有查詢快取,此期間其他連線無法訪問查詢快取,從而導致伺服器僵死,so儘量使查詢快取空間較小,控制伺服器僵死在非常短的時間內】
歡迎個人轉載,但須在文章頁面明顯位置給出原文連線;
未經作者同意必須保留此段宣告、不得隨意修改原文、不得用於商業用途,否則保留追究法律責任的權利。

【 CSDN 】:csdn.zxiaofan.com
【GitHub】:github.zxiaofan.com

如有任何問題,歡迎留言。祝君好運!
Life is all about choices! 
將來的你一定會感激現在拼命的自己!