MySQL查詢快取 --《高效能MySQL》讀書筆記
阿新 • • 發佈:2019-02-05
Query Cache(QC)
快取完整的Select結果,當查詢命中該快取,MySQL會立刻返回結果,跳過解析、優化和執行階段。
1、如何判斷快取命中
快取存放在一個引用表中,通過雜湊值引用。雜湊值包括查詢本身、待查資料庫、客戶端協議版本等可能影響返回結果的資訊。
注:
“如果查詢中包含一個不確定的函式,MySQL則不會檢查查詢快取”?
錯誤。MySQL檢查查詢快取時,僅僅檢測SQL語句是否以sel(大小寫不敏感)開頭,還沒有解析SQL語句。
b)“如果查詢語句中包含任何不確定函式,則查詢快取中是找不到快取結果的”
正解。即使執行了,結果也不會放在查詢快取中。
MySQL只要發現不能被快取的部分,將禁止此查詢被快取。
如果查詢中帶有current_date,最好直接寫死'2016-01-25',
缺點:
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)
Note:
- 當表被lock tables鎖住時,仍可以通過查詢快取返回資料。
- 任何字元不同(包括空格、註釋)都會導致快取的不命中。
- 不會被快取:①查詢語句包含不確定資料(如函式now()、current_date());②不同使用者返回不同結果current_user()、connection_id());③包含自定義函式、儲存函式、使用者變數、臨時表、mysql中的系統表、包含列級別許可權的表等等。
- 開啟查詢快取會對讀寫操作帶來額外的消耗;
- 讀查詢開始前必須檢查是否命中;
- 如果讀查詢可被快取但還未被快取,會將其結果存入查詢快取(額外消耗);
- 寫資料時,對應表所有快取都失效,如果查詢快取非常大或碎片很多,將帶來大量系統消耗。
- 查詢快取加鎖排他。
- 伺服器啟動;
- 初始化查詢快取所需記憶體;(此記憶體池是一個完整的空閒塊,大小為配置的查詢快取大小減去維護查詢快取資料結構所需空間<約40K>)
- 查詢結果若需要快取,MySQL從快取池申請一個數據塊用於儲存,該塊大於引數query_cache_min_res_unit,即使查詢結果遠小於query_cache_min_res_unit。【查詢開始返回結果就分配空間,無法預估查詢結果的大小,So無法為每個查詢結果精確分配大小合適的快取空間】
- 快取時,MySQL優先選擇儘可能小的資料塊,若該塊空間不夠,將申請新的儘可能小的資料塊;(亦可能選擇較大的,此不深究);若該塊有剩餘,MySQL將其釋放,並放入空閒部分。
- 分配資料塊需先鎖住空間塊,再找到合適大小,so相對耗時,MySQL儘量避免。
- 碎片:若平均查詢結果非常小,伺服器併發地向兩個連線返回結果。返回結果後MySQL回收剩餘資料塊時,發現回收的塊小於query_cache_min_res_unit,不能直接在後續的記憶體塊中分配使用,即產生碎片。
- 命中率: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】 |
- 關閉快取後重啟MySQL:net stop/start mysql57
- 一定要先關閉快取,不能在執行時設定引數關閉。
- C:\ProgramData\MySQL\MySQL Server 5.7\my.ini檔案:query_cache_type=0,query_cache_size=0
- 開啟快取是要消耗資源的;
- 多次執行相同查詢,開啟快取效果更佳;
- 關閉快取後,首次執行雖比開啟快取節省時間,但依舊比多次平均執行耗時。
- 執行a語句時,黑屏總比navicat耗時?
- 碎片整理:flush query cache【將所有查詢快取重新排序,並將所有空閒空間聚集起來】
- 清空快取:reset query cache【加鎖訪問所有查詢快取,此期間其他連線無法訪問查詢快取,從而導致伺服器僵死,so儘量使查詢快取空間較小,控制伺服器僵死在非常短的時間內】
歡迎個人轉載,但須在文章頁面明顯位置給出原文連線;
未經作者同意必須保留此段宣告、不得隨意修改原文、不得用於商業用途,否則保留追究法律責任的權利。
【 CSDN 】:csdn.zxiaofan.com
【GitHub】:github.zxiaofan.com
如有任何問題,歡迎留言。祝君好運!
Life is all about choices!
將來的你一定會感激現在拼命的自己!