Query Cache(查詢緩存,以下簡稱QC)存儲SELECT語句及其產(chǎn)生的數(shù)據(jù)結(jié)果,特別適用于:頻繁提交同一個語句,并且該表數(shù)據(jù)變化不是很頻繁的場景,例如一些靜態(tài)頁面,或者頁面中的某塊不經(jīng)常發(fā)生變化的信息。QC有可能會從InnoDB Buffer Pool或者MyISAM key buffer里讀取結(jié)果。 由于QC需要緩存最新數(shù)據(jù)結(jié)果,因此表數(shù)據(jù)發(fā)生任何變化(INSERT、UPDATE、DELETE或其他可能產(chǎn)生數(shù)據(jù)變化的操作),都會導(dǎo)致QC被刷新。 根據(jù)MySQL官方的測試,QC的優(yōu)劣分別是: 1、如果對一個表執(zhí)行簡單的查詢,但每次查詢都不一樣的話,打開QC后,性能反而下降了13%左右。但通常實(shí)際業(yè)務(wù)中,通常不會只有這種請求,因此實(shí)際影響應(yīng)該比這個小一些。 2、如果對一個只有一行數(shù)據(jù)的表進(jìn)行查詢,則可以提升238%,這個效果還是非常不錯的。 因此,如果是在一個更新頻率非常低而只讀查詢頻率非常高的場景下,打開QC還是比較有優(yōu)勢的,其他場景下,則不建議使用。而且,QC一般也維持在100MB以內(nèi)就夠了,沒必要設(shè)置超過數(shù)百M(fèi)B。 QC嚴(yán)格要求2次SQL請求要完全一樣,包括SQL語句,連接的數(shù)據(jù)庫、協(xié)議版本、字符集等因素都會影響,下面幾個例子中的SQL會被認(rèn)為是完全不一樣而不會使用同一個QC內(nèi)存塊: mysql> set names latin1; SELECT * FROM table_name; mysql> set names latin1; select * from table_name; mysql> set names utf8; select * from table_name; 此外,QC也不適用于下面幾個場景: 1、子查詢或者外層查詢; 2、存儲過程、存儲函數(shù)、觸發(fā)器、event中調(diào)用的SQL,或者引用到這些結(jié)果的; 3、包含一些特殊函數(shù)時(shí),例如:BENCHMARK()、CURDATE()、CURRENT_TIMESTAMP()、NOW()、RAND()、UUID()等等; 4、讀取mysql、INFORMATION_SCHEMA、performance_schema 庫數(shù)據(jù)的; 5、類似SELECT…LOCK IN SHARE MODE、SELECT…FOR UPDATE、SELECT..INTO OUTFILE/DUMPFILE、SELECT..WHRE…IS NULL等語句; 6、SELECT執(zhí)行計(jì)劃用到臨時(shí)表(TEMPORARY TABLE); 7、未引用任何表的查詢,例如 SELECT 1+1 這種; 8、產(chǎn)生了 warnings 的查詢; 9、SELECT語句里加了 SQL_NO_CACHE 關(guān)鍵字; 更加奇葩的是,MySQL在從QC中取回結(jié)果前,會先判斷執(zhí)行SQL的用戶是否有全部庫、表的SELECT權(quán)限,如果沒有,則也不會使用QC。 相比下面這個,其實(shí)上面所說的都不重要。 最為重要的是,在MySQL里QC是由一個全局鎖在控制,每次更新QC的內(nèi)存塊都需要進(jìn)行鎖定。 我們可以通過 PROFILING 功能來查看 QC 相關(guān)的一些鎖競爭,例如像下面這樣的: · Waiting for query cache lock · Waiting on query cache mutex 或者,也可以通過執(zhí)行 SHOW PROCESSLIST 來看線程的狀態(tài),例如: · checking privileges on cached query 檢查用戶是否有權(quán)限讀取QC中的結(jié)果集 · checking query cache for query 檢查本次查詢結(jié)果是否已經(jīng)存儲在QC中 · invalidating query cache entries 由于相關(guān)表數(shù)據(jù)已經(jīng)修改了,因此將QC中的內(nèi)存記錄被標(biāo)記為失效 · sending cached result to client 從QC中,將緩存后的結(jié)果返回給客戶程序 · storing result in query cache 將查詢結(jié)果緩存到QC中 如果可以頻繁看到上述幾種狀態(tài),那么說明當(dāng)前QC基本存在比較重的競爭。 說了這么多廢話,其實(shí)核心要點(diǎn)就一個: 1、同時(shí)設(shè)置選項(xiàng) query_cache_type = 0 和 query_cache_size = 0; 2、如果用源碼編譯MySQL的話,編譯時(shí)增加參數(shù) --without-query-cache 即可; 延伸閱讀: |
|