《MySQL面試小抄》查詢緩存機(jī)制終面
我是肥哥,一名不專業(yè)的面試官!
我是囧囧,一名積極找工作的小菜鳥!
囧囧表示:小白面試最怕的就是面試官問的知識(shí)點(diǎn)太籠統(tǒng),自己無法快速定位到關(guān)鍵問題點(diǎn)!!!
本期主要面試考點(diǎn)
面試官考點(diǎn)之簡(jiǎn)述一下什么是查詢緩存機(jī)制?
面試官考點(diǎn)之查詢?nèi)绾蚊芯彺妫?
面試官考點(diǎn)之什么場(chǎng)景下SQL和結(jié)果集不會(huì)被緩存?
面試官考點(diǎn)之什么場(chǎng)景下會(huì)導(dǎo)致MySQL緩存失效?
面試官考點(diǎn)之查詢緩存是如何進(jìn)行內(nèi)存管理的?
面試官考點(diǎn)之MySQL是一次性分配所有的內(nèi)存空間嗎?
面試官考點(diǎn)之緩存中的內(nèi)存碎片無法避免,那么有什么辦法優(yōu)化嗎?
面試官考點(diǎn)之MySQL4.0提出了查詢緩存,它設(shè)計(jì)出來是為了加速哪些查詢場(chǎng)景?
面試官考點(diǎn)之MySQL5.6中默認(rèn)禁用,8.0以后完全移除,造成這個(gè)改變的原因是什么?
面試官考點(diǎn)之生產(chǎn)環(huán)境要不要開啟MySQL緩存?
面試官考點(diǎn)之簡(jiǎn)述一下什么是查詢緩存機(jī)制?
MySQL服務(wù)器高負(fù)載情況下,我們需要采取一種措施給服務(wù)器減輕壓力,一個(gè)復(fù)雜的查詢是非常消耗性能的,
其中磁盤IO又占據(jù)主要資源,緩存是對(duì)系統(tǒng)性能優(yōu)化的一種重要手段。
查詢緩存機(jī)制設(shè)計(jì)是為了從根本上減少磁盤IO次數(shù),MySQL開啟緩存后,將SQL和結(jié)果集以鍵值對(duì)KV的形式存儲(chǔ)在內(nèi)存中。
當(dāng)相同的SQL再次進(jìn)入,MySQL識(shí)別是相同查詢喉,會(huì)直接返回緩存在內(nèi)存中的結(jié)果集。
避免再次進(jìn)行一系列復(fù)雜的解析優(yōu)化和磁盤IO過程。
面試官考點(diǎn)之查詢?nèi)绾蚊芯彺妫?/h3>
select id from user;
select id FROM user;
上面語句能命中緩存嗎?
select id from user;
select id FROM user;
上面語句能命中緩存嗎?
MySQL緩存命中機(jī)制有嚴(yán)格苛刻的要求,在判斷命中前,MySQL不會(huì)對(duì)SQL做任何的解析處理。
SQL上的任何字符的不同,如大小寫、空格、注釋等都會(huì)導(dǎo)致緩存不命中
所以上面查詢時(shí)無法命中緩存的。
面試官考點(diǎn)之什么場(chǎng)景下SQL和結(jié)果集不會(huì)被緩存?
或者說緩存規(guī)則是什么?
第一種情況:查詢語句中包含不確定數(shù)據(jù)
例如查詢語句中包含不確定函數(shù):NOW()、CURRENT_DATE()等。
因?yàn)槊看螆?zhí)行這類帶了不確定數(shù)據(jù)的查詢所返回結(jié)果可能是不同的。
第二種情況:超過了query_cache_limit預(yù)設(shè)閾值
超出了緩存內(nèi)存能承受的范圍,將放棄緩存!
面試官考點(diǎn)之什么場(chǎng)景下會(huì)導(dǎo)致MySQL緩存失效?
任何對(duì)于表結(jié)構(gòu)或者表數(shù)據(jù)的更新操作,一定會(huì)造成查詢緩存中的數(shù)據(jù)失效,同時(shí)查詢緩存值的相關(guān)條目也會(huì)被清空。
MySQL判定有更新操作,就會(huì)設(shè)置所有的查詢緩存失效。
面試官考點(diǎn)之查詢緩存是如何進(jìn)行內(nèi)存管理的?
MySQL服務(wù)啟動(dòng),緩存機(jī)制會(huì)在內(nèi)存中開辟一塊內(nèi)存,
其中會(huì)劃分出一塊區(qū)域
專用來管理維護(hù)緩存數(shù)據(jù)的元數(shù)據(jù)。
例如空間內(nèi)存、數(shù)據(jù)表和查詢結(jié)果的映射,SQL和查詢結(jié)果的映射
MySQL緩存機(jī)制將剩余的空閑空間分為一個(gè)個(gè)小數(shù)據(jù)塊,用來存儲(chǔ)緩存結(jié)果。
每個(gè)小塊中存儲(chǔ)自身的類型,大小和查詢結(jié)果數(shù)據(jù),還有指向前后內(nèi)存塊的指針
面試官考點(diǎn)之MySQL是一次性分配所有的內(nèi)存空間嗎?
MySQL因?yàn)闊o法預(yù)知查詢結(jié)果大小,所以無法為每個(gè)查詢結(jié)果精確分配大小恰好匹配的緩存空間。
MySQL緩存機(jī)制采用的是邊查邊存,動(dòng)態(tài)的去申請(qǐng)緩存內(nèi)存。
一條SQL查詢緩存分配內(nèi)存過程是怎么樣的?
當(dāng)有查詢結(jié)果需要緩存的時(shí)候,MySQL緩存機(jī)制會(huì)在SQL查詢開始(還未得到結(jié)果)時(shí)就去申請(qǐng)一塊內(nèi)存空間(小數(shù)據(jù)塊),在不斷查詢中,如果發(fā)現(xiàn)不夠則繼續(xù)申請(qǐng)
,如果存儲(chǔ)完時(shí)有空余則釋放多余的內(nèi)存空間
。
如果余下的需要回收的空間很小,小于query_cache_min_res_unit,不能再次被使用,可能會(huì)造成內(nèi)存碎片,影響查詢性能。
面試官考點(diǎn)之緩存中的內(nèi)存碎片無法避免,那么有什么辦法優(yōu)化嗎?
沒有什么辦法能夠完全避免內(nèi)存碎片,但是選擇合適的
query_cache_min_res_unit
可以減少由碎片導(dǎo)致的內(nèi)存空間浪費(fèi)。
值太小,則浪費(fèi)的空間更少,但是會(huì)導(dǎo)致頻繁的內(nèi)存塊申請(qǐng)操作
如果設(shè)置得太大,那么碎片會(huì)很多
調(diào)整合適的值其實(shí)是在平衡內(nèi)存浪費(fèi)和CPU消耗
那么我如何確定這個(gè)平衡值?
可以通過內(nèi)存實(shí)際消耗,計(jì)算單個(gè)查詢的平均緩存大小
(query_cache_size - Qcache_free_memory)/ Qcache_queries_in_cahce
通過查看閑置內(nèi)存塊數(shù)量(Qcahce_free_blocks)來觀察碎片。
如果產(chǎn)生的碎片過多,通過什么方法可以整理碎片?
通過FLUSH_QUERY_CAHCE清理碎片
這個(gè)命令將所有的查詢緩存重新排序,
并將所有的空閑空間都聚焦到查詢緩存的一塊區(qū)域上。
面試官考點(diǎn)之MySQL4.0提出了查詢緩存,它設(shè)計(jì)出來是為了加速哪些查詢場(chǎng)景?
1、并發(fā)性和查詢QPS不高
2、被訪問的底層數(shù)據(jù)本質(zhì)上是靜態(tài)或半靜態(tài)的
3、查詢密集型應(yīng)用,更新頻率非常低而只讀查詢頻率非常高的場(chǎng)景
面試官考點(diǎn)之MySQL5.6中默認(rèn)禁用,8.0以后完全移除,造成這個(gè)改變的原因是什么?
理想情況下,上述查詢場(chǎng)景非常適合使用查詢緩存,但是實(shí)際的業(yè)務(wù)系統(tǒng)都是有CRUD操作
的。
在MySQL里QC是由一個(gè)全局鎖在控制,每次更新QC的內(nèi)存塊都需要進(jìn)行鎖定,數(shù)據(jù)更新頻繁,就會(huì)不斷的失效緩存操作,同時(shí)緩存失效會(huì)造成大量的查詢緩存碎片化
,還會(huì)導(dǎo)致服務(wù)器的負(fù)載升高,影響數(shù)據(jù)庫(kù)的穩(wěn)定性。
所以MySQL官方經(jīng)過抉擇,果斷移除了查詢緩存模塊。
面試官考點(diǎn)之生產(chǎn)環(huán)境要不要開啟MySQL緩存?
建議不開啟
根據(jù)MySQL官方的測(cè)試,如果對(duì)一個(gè)表執(zhí)行簡(jiǎn)單的查詢,
設(shè)置每次查詢都不一樣,
打開QC后,性能反而下降了13%左右
當(dāng)然實(shí)際業(yè)務(wù)中,不會(huì)都是這種不同的請(qǐng)求,因此實(shí)際影響應(yīng)該比這個(gè)小一些。
MySQL查詢緩存的目的是為了提升查詢性能,但它本身也是有性能開銷的。
需要在合適的業(yè)務(wù)場(chǎng)景下(讀寫壓力模型)
使用
不合適的業(yè)務(wù)場(chǎng)景不但不能提升查詢性能,查詢緩存反而會(huì)變成MySQL的瓶頸。
對(duì)寫密集型的應(yīng)用場(chǎng)景來說,禁用緩存反而提高性能。
隨緣更新,整理不易,歡迎聯(lián)系小白討論,大神巴巴請(qǐng)繞路!
更多精彩內(nèi)容,歡迎關(guān)注微信公眾號(hào):囧么肥事 (或搜索:jiongmefeishi)