《MySQL面試小抄》查詢緩存機制終面
我是肥哥,一名不專業(yè)的面試官并齐!
我是囧囧漏麦,一名積極找工作的小菜鳥客税!
囧囧表示:小白面試最怕的就是面試官問的知識點太籠統(tǒng),自己無法快速定位到關(guān)鍵問題點K赫辍8堋!
本期主要面試考點
面試官考點之簡述一下什么是查詢緩存機制捏膨?
面試官考點之查詢?nèi)绾蚊芯彺妫?
面試官考點之什么場景下SQL和結(jié)果集不會被緩存秧均?
面試官考點之什么場景下會導致MySQL緩存失效?
面試官考點之查詢緩存是如何進行內(nèi)存管理的号涯?
面試官考點之MySQL是一次性分配所有的內(nèi)存空間嗎目胡?
面試官考點之緩存中的內(nèi)存碎片無法避免,那么有什么辦法優(yōu)化嗎诚隙?
面試官考點之MySQL4.0提出了查詢緩存讶隐,它設(shè)計出來是為了加速哪些查詢場景?
面試官考點之MySQL5.6中默認禁用久又,8.0以后完全移除巫延,造成這個改變的原因是什么?
面試官考點之生產(chǎn)環(huán)境要不要開啟MySQL緩存地消?
面試官考點之簡述一下什么是查詢緩存機制炉峰?
MySQL服務(wù)器高負載情況下,我們需要采取一種措施給服務(wù)器減輕壓力脉执,一個復雜的查詢是非常消耗性能的疼阔,
其中磁盤IO又占據(jù)主要資源,緩存是對系統(tǒng)性能優(yōu)化的一種重要手段半夷。
查詢緩存機制設(shè)計是為了從根本上減少磁盤IO次數(shù)婆廊,MySQL開啟緩存后,將SQL和結(jié)果集以鍵值對KV的形式存儲在內(nèi)存中巫橄。
當相同的SQL再次進入淘邻,MySQL識別是相同查詢喉,會直接返回緩存在內(nèi)存中的結(jié)果集湘换。
避免再次進行一系列復雜的解析優(yōu)化和磁盤IO過程宾舅。
面試官考點之查詢?nèi)绾蚊芯彺妫?/h3>
select id from user;
select id FROM user;
上面語句能命中緩存嗎?
select id from user;
select id FROM user;
上面語句能命中緩存嗎?
MySQL緩存命中機制有嚴格苛刻的要求彩倚,在判斷命中前筹我,MySQL不會對SQL做任何的解析處理。
SQL上的任何字符的不同帆离,如大小寫蔬蕊、空格、注釋等都會導致緩存不命中
所以上面查詢時無法命中緩存的哥谷。
面試官考點之什么場景下SQL和結(jié)果集不會被緩存袁串?
或者說緩存規(guī)則是什么概而?
第一種情況:查詢語句中包含不確定數(shù)據(jù)
例如查詢語句中包含不確定函數(shù):NOW()、CURRENT_DATE()等囱修。
因為每次執(zhí)行這類帶了不確定數(shù)據(jù)的查詢所返回結(jié)果可能是不同的。
第二種情況:超過了query_cache_limit預(yù)設(shè)閾值
超出了緩存內(nèi)存能承受的范圍王悍,將放棄緩存破镰!
面試官考點之什么場景下會導致MySQL緩存失效?
任何對于表結(jié)構(gòu)或者表數(shù)據(jù)的更新操作压储,一定會造成查詢緩存中的數(shù)據(jù)失效鲜漩,同時查詢緩存值的相關(guān)條目也會被清空。
MySQL判定有更新操作集惋,就會設(shè)置所有的查詢緩存失效孕似。
面試官考點之查詢緩存是如何進行內(nèi)存管理的?
MySQL服務(wù)啟動刮刑,緩存機制會在內(nèi)存中開辟一塊內(nèi)存喉祭,
其中會劃分出一塊區(qū)域
專用來管理維護緩存數(shù)據(jù)的元數(shù)據(jù)。
例如空間內(nèi)存雷绢、數(shù)據(jù)表和查詢結(jié)果的映射泛烙,SQL和查詢結(jié)果的映射
MySQL緩存機制將剩余的空閑空間分為一個個小數(shù)據(jù)塊,用來存儲緩存結(jié)果翘紊。
每個小塊中存儲自身的類型蔽氨,大小和查詢結(jié)果數(shù)據(jù),還有指向前后內(nèi)存塊的指針
面試官考點之MySQL是一次性分配所有的內(nèi)存空間嗎帆疟?
MySQL因為無法預(yù)知查詢結(jié)果大小鹉究,所以無法為每個查詢結(jié)果精確分配大小恰好匹配的緩存空間。
MySQL緩存機制采用的是邊查邊存踪宠,動態(tài)的去申請緩存內(nèi)存自赔。
一條SQL查詢緩存分配內(nèi)存過程是怎么樣的?
當有查詢結(jié)果需要緩存的時候殴蓬,MySQL緩存機制會在SQL查詢開始(還未得到結(jié)果)時就去申請一塊內(nèi)存空間(小數(shù)據(jù)塊)匿级,在不斷查詢中,如果發(fā)現(xiàn)不夠則繼續(xù)申請
染厅,如果存儲完時有空余則釋放多余的內(nèi)存空間
痘绎。
如果余下的需要回收的空間很小,小于query_cache_min_res_unit肖粮,不能再次被使用孤页,可能會造成內(nèi)存碎片,影響查詢性能涩馆。
面試官考點之緩存中的內(nèi)存碎片無法避免行施,那么有什么辦法優(yōu)化嗎允坚?
沒有什么辦法能夠完全避免內(nèi)存碎片,但是選擇合適的
query_cache_min_res_unit
可以減少由碎片導致的內(nèi)存空間浪費蛾号。
值太小稠项,則浪費的空間更少,但是會導致頻繁的內(nèi)存塊申請操作
如果設(shè)置得太大鲜结,那么碎片會很多
調(diào)整合適的值其實是在平衡內(nèi)存浪費和CPU消耗
那么我如何確定這個平衡值展运?
可以通過內(nèi)存實際消耗,計算單個查詢的平均緩存大小
(query_cache_size - Qcache_free_memory)/ Qcache_queries_in_cahce
通過查看閑置內(nèi)存塊數(shù)量(Qcahce_free_blocks)來觀察碎片精刷。
如果產(chǎn)生的碎片過多拗胜,通過什么方法可以整理碎片?
通過FLUSH_QUERY_CAHCE清理碎片
這個命令將所有的查詢緩存重新排序怒允,
并將所有的空閑空間都聚焦到查詢緩存的一塊區(qū)域上埂软。
面試官考點之MySQL4.0提出了查詢緩存,它設(shè)計出來是為了加速哪些查詢場景纫事?
1勘畔、并發(fā)性和查詢QPS不高
2、被訪問的底層數(shù)據(jù)本質(zhì)上是靜態(tài)或半靜態(tài)的
3儿礼、查詢密集型應(yīng)用咖杂,更新頻率非常低而只讀查詢頻率非常高的場景
面試官考點之MySQL5.6中默認禁用,8.0以后完全移除蚊夫,造成這個改變的原因是什么诉字?
理想情況下,上述查詢場景非常適合使用查詢緩存知纷,但是實際的業(yè)務(wù)系統(tǒng)都是有CRUD操作
的壤圃。
在MySQL里QC是由一個全局鎖在控制,每次更新QC的內(nèi)存塊都需要進行鎖定琅轧,數(shù)據(jù)更新頻繁伍绳,就會不斷的失效緩存操作,同時緩存失效會造成大量的查詢緩存碎片化
乍桂,還會導致服務(wù)器的負載升高冲杀,影響數(shù)據(jù)庫的穩(wěn)定性。
所以MySQL官方經(jīng)過抉擇睹酌,果斷移除了查詢緩存模塊权谁。
面試官考點之生產(chǎn)環(huán)境要不要開啟MySQL緩存?
建議不開啟
根據(jù)MySQL官方的測試憋沿,如果對一個表執(zhí)行簡單的查詢旺芽,
設(shè)置每次查詢都不一樣,
打開QC后,性能反而下降了13%左右
當然實際業(yè)務(wù)中采章,不會都是這種不同的請求运嗜,因此實際影響應(yīng)該比這個小一些。
MySQL查詢緩存的目的是為了提升查詢性能悯舟,但它本身也是有性能開銷的担租。
需要在合適的業(yè)務(wù)場景下(讀寫壓力模型)
使用
不合適的業(yè)務(wù)場景不但不能提升查詢性能,查詢緩存反而會變成MySQL的瓶頸图谷。
對寫密集型的應(yīng)用場景來說翩活,禁用緩存反而提高性能。
隨緣更新便贵,整理不易,歡迎聯(lián)系小白討論冗荸,大神巴巴請繞路承璃!
更多精彩內(nèi)容,歡迎關(guān)注微信公眾號:囧么肥事 (或搜索:jiongmefeishi)