當(dāng)查詢命中緩存時冒冬,立即返回結(jié)果舱沧。跳過了解析 優(yōu)化和執(zhí)行階段
什么時候不會被緩存
查詢涉及的相關(guān)表數(shù)據(jù)發(fā)生變化時
查詢緩存系統(tǒng)會跟蹤查詢中涉及的每個表溉愁,如果這些表發(fā)生變化屋摇,那么和這個表相關(guān)的所有的緩存數(shù)據(jù)都將失效揩魂。這種機制效率看起來比較低,因為數(shù)據(jù)表變化時很有可能對應(yīng)的查詢結(jié)果并沒有變更炮温,但是這種簡單實現(xiàn)代價很小火脉,而這點對于一個非常繁忙的系統(tǒng)來說非常重要。
查詢語句任何細微變化時
MySql將查詢結(jié)果存放在引用表中柒啤,通過一個哈希值引用倦挂,這個哈希值包含了如下因素,查詢本身担巩、要查詢得數(shù)據(jù)庫方援、客戶端協(xié)議的版本等其他可能會影響返回結(jié)果的信息,
判斷緩存是否命中時涛癌,MySql不會解析犯戏、參數(shù)化送火、任何規(guī)整查詢sql的操作,直接使用客戶端發(fā)來的原始sql語句先匪。任何字符上的不同种吸,如空格、注釋都會導(dǎo)致緩存不被命中呀非。
查詢語句中有不確定數(shù)據(jù)時
- 包含
NOW()
坚俗、CURRENT_DATE()
、CURRENT_USER()
岸裙、CONNECTION_ID()
等變化的信息 - 包含任何用戶自定義函數(shù)猖败,存儲函數(shù),用戶變量哥桥,臨時表辙浑,MySQL系統(tǒng)表 等
- 包含 子查詢,存儲過程(子查詢的sql不是完整的拟糕,而是運行時被計算出來的)
查詢結(jié)果太大
查詢緩存內(nèi)存用完
如果查詢語句中包含任何的不確定函數(shù)判呕,那么在查詢緩存中是不可 能找到緩存結(jié)果的。因為即使之前剛剛執(zhí)行了這樣的查詢送滞,結(jié)果也不會放在查詢緩存中侠草。 MySQL在任何時候只要發(fā)現(xiàn)不能被緩存的部分,就會禁止這個查詢被緩存犁嗅。
查詢緩存的缺點
對讀和寫操作帶來額外的消耗
- 讀查詢在開始之前必須先檢查是否命中緩存
- MySql執(zhí)行完SQL時边涕,如果該SQL可以緩存,但是此時還沒被緩存褂微,會將數(shù)據(jù)寫入緩存中
- 影響寫操作功蜓,執(zhí)行寫入操作時,將此表對應(yīng)的所有緩存都設(shè)置失效宠蚂。對查詢緩存失效的操作是靠全局鎖保護的式撼。防止此時又被緩存了舊數(shù)據(jù)。所有與該表相關(guān)的查詢都要等待該鎖求厕。無論此查詢是否命中緩存著隆,以及檢測緩存是否失效。 如果緩存大呀癣,或者碎片很多美浦,那么就會有很大的系統(tǒng)消耗。(設(shè)置了很大的查詢緩存的時候)
事務(wù)對查詢緩存的影響
對InnoDB用戶來說项栏,事務(wù)的一些特性會限制查詢緩存的使用浦辨。當(dāng)一個語句在事務(wù)中修改了某個表,MySQL會將這個表的對應(yīng)的查詢緩存都設(shè)置失效忘嫉,而事實上荤牍,InnoDB的多版本特性會暫時將這個修改對其他事務(wù)屏蔽案腺。在這個事務(wù)提交之前庆冕,這個表的相關(guān)查詢是無法被緩存的康吵,所以所有在這個表上面的查詢一內(nèi)部或外部的事務(wù)——都只能在該事務(wù)提交后才被緩存。因此访递,長時間運行的事務(wù)晦嵌,會大大降低查詢緩存的命中率。
緩存對系統(tǒng)的影響
只有當(dāng)緩存帶來的資源節(jié)約大于其本身的資源消耗時才會給系統(tǒng)帶來性能提升
適合做緩存的查詢
- 匯總查詢拷姿,如 count, max 等
- 復(fù)雜的查詢惭载,但結(jié)果少。如多表關(guān)聯(lián)后需要分組响巢,排序在分頁的查詢描滔。同時涉及的表更新操作少于查詢操作,防止緩存頻發(fā)失效
命中率的計算
一個判斷查詢緩存是否有效的直接數(shù)據(jù)是命中率踪古,就是使用查詢緩存返回結(jié)果占總查詢的比率含长。當(dāng)MySQL接收到一個SELECT查詢的時候,要么增加Qcache hits的值伏穆,要么增加Com select的值拘泞。所以查詢緩存命中率可以由如下公式計算:Qcache hits / (Qcache hits+Com select)
命中率低不代表性能提升少
不過,查詢緩存命中率是一個很難判斷的數(shù)值枕扫。命中率多大才是好的命中率陪腌?具體情況要具體分析。只要查詢緩存帶來的效率提升大于查詢緩存帶來的額外消耗烟瞧,即使30%命中率對系統(tǒng)性能提升也有很大好處诗鸭。另外,緩存了哪些查詢也很重要参滴,例如强岸,被緩存的查詢本身消耗非常巨大,那么即使緩存命中率非常低卵洗,也仍然會對系統(tǒng)性能提升有好處请唱。所以,沒有一個簡單的規(guī)則可以判斷查詢緩存是否對系統(tǒng)有好處过蹂。
命中和寫入的比率
即Qcache hits和Qcache inserts的比值十绑。根據(jù)經(jīng)驗來看,當(dāng)這個比值大于3:1時通常查詢緩存是有效的酷勺,不過這個比率最好能夠達到10:1本橙。如果你的應(yīng)用沒有達到這個比率,那么就可以考慮禁用查詢緩存了脆诉,除非你能夠通過精確的計算得知:命中帶來的性能提升大于緩存失效的消耗甚亭,并且查詢緩存并沒有成為系統(tǒng)的瓶頸贷币。
緩存失效的一些指標(biāo)檢查
- 更新導(dǎo)致
可以通過參數(shù)Com*來查看數(shù)據(jù)修改的情況(包括Com update,Com delete,等等) - 緩存空間不足
通過Qcache lowmem prunes來查看有多少次失效是由于內(nèi)存不足導(dǎo)致的. - 緩存的數(shù)據(jù)沒有被查詢
查看Com select和Qcache inserts的相對值。
如果每次查詢操作都是緩存未命中亏狰,然后需要將查詢結(jié)果放到緩存中役纹,那么Qcache inserts的大小應(yīng)該和Com select相當(dāng)。所以在緩存完成預(yù)熱后暇唾,我們總希 望看到Qcache inserts遠遠小于Com select促脉。不過由于緩存和服務(wù)器內(nèi)部的復(fù)雜和多樣性,仍然很難說策州,這個比率是多少才是一個合適的值瘸味。
緩存空間的設(shè)置和使用
并非越大越好
每一個應(yīng)用程序都會有一個“最大緩存空間”,甚至對一些純讀的應(yīng)用來說也一樣够挂。最大緩存空間是能夠緩存所有可能查詢結(jié)果的緩存空間總和旁仿。理論上,對多數(shù)應(yīng)用來說孽糖, 這個數(shù)值都會非常大枯冈。而實際上,由于緩存失效的原因梭姓,大多數(shù)應(yīng)用最后使用的緩存空間都比預(yù)想的要小霜幼。即使你配置了足夠大的緩存空間,由于不斷地失效誉尖,導(dǎo)致緩存空間 一直都不會接近“最大緩存空間”
設(shè)置一個合理值
通匙锛龋可以通過觀察查詢緩存內(nèi)存的實際使用情況,來確定是否需要縮小或者擴大查詢緩存铡恕。如果查詢緩存空間長時間都有剩余琢感,那么建議縮小探熔;如果經(jīng)常由于空間不足而導(dǎo)致查詢緩存失效驹针,那么則需要增大查詢緩存。不過需要注意诀艰,如果查詢緩存達到了幾十兆 這樣的數(shù)量級柬甥,是有潛在危險的。(這和硬件以及系統(tǒng)壓力大小有關(guān))其垄。
查詢緩存的一些配置參數(shù)
...
參考資料
- 《高性能MySql》