mysql查詢快取

2021-09-13 18:27:38 字數 4823 閱讀 1108

一:快取條件,原理

mysql query cache是用來快取我們所執行的select語句以及該語句的結果集,mysql在實現query cache的具體技術細節上類似典型的kv儲存,就是將select語句和該查詢語句的結果集做了乙個hash對映並儲存在一定的記憶體區域中。當客戶端發起sql查詢時,query cache的查詢邏輯是,先對sql進行相應的許可權驗證,接著就通過query cache來查詢結果(注意必須是完全相同,即使多乙個空格或者大小寫不 同都認為不同,即使完全相同的sql,如果使用不同的字符集、不同的協議等也會被認為是不同的查詢而分別進行快取)。它不需要經過optimizer模組進行執行計畫的分析優化,更不需要發生同任何儲存引擎的互動,減少了大量的磁碟io和cpu運 算,所以有時候效率非常高。

查詢快取的工作流程如下:

1:命中條件

快取存在乙個hash表中,通過查詢sql,查詢資料庫,客戶端協議等作為key.在判斷是否命中前,mysql不會解析sql,而是直接使用sql去查詢快取,sql任何字元上的不同,如空格,注釋,都會導致快取不命中.

如果查詢中有不確定資料,例如current_date()和now()函式,那麼查詢完畢後則不會被快取.所以,包含不確定資料的查詢是肯定不會找到可用快取的

2:工作流程

1. 伺服器接收sql,以sql和一些其他條件為key查詢快取表(額外效能消耗)

2. 如果找到了快取,則直接返回快取(效能提公升)

3. 如果沒有找到快取,則執行sql查詢,包括原來的sql解析,優化等.

4. 執行完sql查詢結果以後,將sql查詢結果存入快取表(額外效能消耗)

二:快取引數

2:快取配置引數解釋

1. query_cache_type: 查詢快取型別,是否開啟快取

可選項a、0(off):關閉 query cache 功能,任何情況下都不會使用 query cache;

b、1(on):開啟 query cache 功能,但是當select語句中使用sql_no_cache提示後,將不使用query cache;

c、2(demand):開啟query cache 功能,但是只有當select語句中使用了sql_cache 提示後,才使用query cache。

備註1:

如果query_cache_type為on而又不想利用查詢快取中的資料,可以用下面的sql:

select sql_no_cache * from my_table where condition;

如果值為2,要使用快取的話,需要使用sql_cache開關引數:

select sql_cache * from my_table where condition;

2. query_cache_size: 快取使用的總記憶體空間大小,單位是位元組,這個值必須是1024的整數倍,否則mysql 會自動調整降低最小量以達到1024的倍數;(感覺這個應該跟檔案系統的blcok大小有關)

3. query_cache_min_res_unit: 分配記憶體塊時的最小單位大小,設定查詢快取query cache每次分配記憶體的最小空間大小,即每個查詢的快取最小占用的記憶體空間大小;

4. query_cache_limit: 允許快取的單條查詢結果集的最大容量,預設是1mb,超過此引數設定的查詢結果集將不會被快取;

5. query_cache_wlock_invalidate: 如果某個資料表被鎖住,是否仍然從快取中返回資料,預設是off,表示仍然可以返回

控制當有寫鎖定發生在表上的時刻是否先失效該錶相關的query cache,如果設定為 1(true),則在寫鎖定的同時將失效該錶相關的所有query cache,如果設定為0(false)則在鎖定時刻仍然允許讀取該錶相關的query cache。

global staus 中 關於 快取的引數解釋:

qcache_free_blocks: 快取池中空閒塊的個數

qcache_free_memory: 快取中空閒記憶體量

qcache_hits: 快取命中次數

qcache_inserts: 快取寫入次數

qcache_lowmen_prunes: 因記憶體不足刪除快取次數

qcache_not_cached: 查詢未被快取次數,例如查詢結果超出快取塊大小,查詢中包含可變函式等

qcache_queries_in_cache: 當前快取中快取的sql數量

qcache_total_blocks: 快取總block數

3:設定配置引數:

set global query_cache_size = 134217728;

4:檢視快取命中次數(是個累加值):

show status like 'qcache_hits'

三:快取資料失效時機

1:在表的結構或資料發生改變時,查詢快取中的資料不再有效。有這些insert、update、 delete、truncate、alter table、drop table或drop database會導致快取資料失效。所以查詢快取適合有大量相同查詢的應用,不適合有大量資料更新的應用。

當某個表正在寫入資料,則這個表的快取(命中檢查,快取寫入等)將會處於失效狀態.在innodb中,如果某個事務修改了表,則這個表的快取在事務提交前都會處於失效狀態,在這個事務提交前,這個表的相關查詢都無法被快取.

2:清理查詢快取 & 減少碎片策略

flush query_cache; 清理查詢快取記憶體碎片

reset query_cache; 從查詢快取中移出所有查詢

flush tables;  關閉所有開啟的表,同時該操作將會清空查詢快取中的內容

1. 選擇合適的block大小

2. 使用 flush query cache 命令整理碎片.這個命令在整理快取期間,會導致其他連線無法使用查詢快取

ps: 清空快取的命令式 reset query cache

四:快取的記憶體管理

快取會在記憶體中開闢一塊記憶體(query_cache_size)來維護快取資料,其中有大概40k的空間是用來維護快取的元資料的(什麼是元資料:例如空間記憶體,資料表和查詢結果的對映,sql和查詢結果的對映等.

mysql將這個大記憶體塊分為小的記憶體塊(query_cache_min_res_unit),每個小塊中儲存自身的型別,大小和查詢結果資料,還有指向前後記憶體塊的指標.

mysql需要設定單個小儲存塊的大小,在sql查詢開始(還未得到結果)時就去申請一塊空間,所以即使你的快取資料沒有達到這個大小,也需要用這 個大小的資料塊去存(這點跟linux檔案系統的block一樣).如果結果超出這個記憶體塊的大小,則需要再去申請乙個記憶體塊.當查詢完成發現申請的記憶體 塊有富餘,則會將富餘的空間釋放掉,這就會造成記憶體碎片問題,見下圖

此處查詢1和查詢2之間的空白部分就是記憶體碎片,這部分空閒記憶體是有查詢1查詢完以後釋放的,假設這個空間大小小於mysql設定的記憶體塊大小,則無法再被使用,造成碎片問題

在查詢開始時申請分配記憶體block需要鎖住整個空閒記憶體區,所以分配記憶體塊是非常消耗資源的.注意這裡所說的分配記憶體是在mysql初始化時就開闢的那塊記憶體上分配的.

五:快取的使用時機 & 效能

衡量開啟快取是否對系統有效能提公升是乙個很難的話題

1. 通過快取命中率判斷, 快取命中率 = 快取命中次數 (qcache_hits) / 查詢次數 (com_select)

2. 通過快取寫入率, 寫入率 = 快取寫入次數 (qcache_inserts) / 查詢次數 (qcache_inserts)

3. 通過 命中-寫入率 判斷, 比率 = 命中次數 (qcache_hits) / 寫入次數 (qcache_inserts), 高效能mysql中稱之為比較能反映效能提公升的指數,一般來說達到3:1則算是查詢快取有效,而最好能夠達到10:1

任何事情過猶不及,尤其對於某些寫頻繁的系統,開啟query cache功能可能並不能讓系統效能有提公升,有時反而會有下降。原因是mysql為了保證query cache快取的內容和實際資料絕對一致,當某個資料表發生了更新、刪除及插入操作,mysql都會強制使所有引用到該錶的查詢sql的query cache失效。對於密集寫操作,啟用查詢快取後很可能造成頻繁的快取失效,間接引發記憶體激增及cpu飆公升,對已經非常忙碌的資料庫系統這是一種極大的負 擔。

六:查詢快取問題分析

七:innodb與查詢快取

innodb會對每個表設定乙個事務計數器,裡面儲存當前最大的事務id.當乙個事務提交時,innodb會使用mvcc中系統事務id最大的事務id跟新當前表的計數器.

只有比這個最大id大的事務能使用查詢快取,其他比這個id小的事務則不能使用查詢快取.

另外,在innodb中,所有有加鎖操作的事務都不使用任何查詢快取

八、其他

query cache因mysql的儲存引擎不同而實現略有差異,比如myisam,快取的結果集儲存在os cache中,而最流行的innodb則放在buffer pool中。

mysql資料快取查詢 Mysql查詢快取

查詢快取 mysql提供了一種快取型別,會快取整個select查詢結果。mysql查詢快取儲存查詢返回的完整結果。當查詢命中該快取,mysql會立即返回結果,跳過了解析 優化和執行階段。以下兩種情況不能被快取 頻繁更新 修改的的表,所有快取資料都會失效,mysql查詢快取會跟蹤查詢中涉及的表,如果這...

mysql 查詢快取

show variables like cache my.cnf設定 mysql慢日誌 mysql有乙個功能就是可以log下來執行的比較慢的sql語句,預設是沒有這個log的,為了開啟這個功能,要修改my.cnf或者在mysql啟動的時候加入一些引數。如果在my.cnf裡面修改,需增加如下幾行 lo...

mysql查詢快取

查詢快取不開啟 r mysql query select username from user where signup date curdate 開啟查詢快取 today date y m d r mysql query select username from user where signup...