0.MySQL基本架構(gòu)
MySQL有客戶端,也有服務(wù)端掰烟,服務(wù)端主要分為Server層和存儲引擎層爽蝴,Server層包括五個部分,分別為連接器媚赖、查詢緩存霜瘪、分析器、優(yōu)化器和執(zhí)行器惧磺∮倍裕基本架構(gòu)圖如下:
1.查詢緩存作用
-
查詢過程
當(dāng)執(zhí)行SQL查詢時,MySQL會先到查詢緩存中查看之前執(zhí)行過該SQL語句磨隘,在查詢緩存中之前執(zhí)行過的語句及其結(jié)果會以key-value形式存放缤底,key對應(yīng)于查詢語句,value對應(yīng)于查詢結(jié)果番捂。如果在查詢緩存中存在該key个唧,則直接返回value,不需要執(zhí)行后面操作设预;如果不存在該key徙歼,則進行分析器、優(yōu)化器鳖枕、執(zhí)行器以及調(diào)用存儲引擎操作魄梯,最后將對應(yīng)結(jié)果以key-value形式寫入查詢緩存,返回value宾符。
-
存在弊端
雖然命中查詢緩存的語句效率非常高酿秸,但是查詢緩存的失效非常頻繁,只要有對一個表的更新魏烫,這個表所有的查詢緩存就回被清空辣苏。對于更新壓力大的數(shù)據(jù)庫來說,查詢緩存的命中率會非常低哄褒。除非你的業(yè)務(wù)就是有一張靜態(tài)表稀蟋,很長時間才會更新一次。比如呐赡,一個系統(tǒng)配置表糊治,那這張表上的查詢才適合使用查詢緩存。
-
解決方案
好在 MySQL 也提供了這種“按需使用”的方式罚舱。你可以將參數(shù) query_cache_type (ini配置文件)設(shè)置成 DEMAND井辜,這樣對于默認的 SQL 語句都不使用查詢緩存。
而對于你確定要使用查詢緩存的語句管闷,可以用 SQL_CACHE 顯式指定粥脚,像下面這個語句一樣:
mysql> select SQL_CACHE * from table_name where ID=10;
需要注意的是包个,MySQL 8.0 版本直接將查詢緩存的整塊功能刪掉了刷允,也就是說 8.0 開始徹底沒有這個功能了。
同時以上查詢緩存語句對于數(shù)據(jù)庫系統(tǒng)表(information_schema/mysql/performance_schema/sys)無效
2.查詢緩存模式
-
查詢緩存模式
mysql>SHOW VARIABLES LIKE 'query_cache_type'; Variable_name Value ---------------- -------- query_cache_type OFF
MySQL5.5默認開啟(ON)
MySQL5.7默認關(guān)閉(OFF)
MySQL8.0不存在該變量
-
my.ini文件設(shè)置查詢緩存模式
# 查詢緩存模式: # 0 : OFF 關(guān)閉 # 1 : ON 緩存所有結(jié)果碧囊,除非select語句使用SQL_NO_CACHE禁用查詢緩存 # 2 : DEMAND 只緩存select語句中通過SQL_CACHE指定需要緩存的查詢 query_cache_type=2
查詢是否命中
mysql>SHOW STATUS LIKE '%Qcache%';
Variable_name Value
----------------------- ----------
Qcache_free_blocks 1
Qcache_free_memory 15709672
Qcache_hits 2 # 表示有多少次命中緩存
Qcache_inserts 1 # 表示多少次未命中緩存然后插入树灶,意思是新來的SQL請求如果在緩存中未找到,不得不執(zhí)行查詢處理糯而,執(zhí)行查詢處理后把結(jié)果insert到查詢緩存中天通。
Qcache_lowmem_prunes 0
Qcache_not_cached 11 # 表示因為query_cache_type的設(shè)置而沒有被緩存的查詢數(shù)量。
Qcache_queries_in_cache 1 # 當(dāng)前緩存中緩存的查詢數(shù)量熄驼。
Qcache_total_blocks 4 # 當(dāng)前緩存的block數(shù)量像寒。
3.驗證查詢緩存
以下試驗以MySQL5.5版本為基礎(chǔ)
3.1查詢緩存模式為ON
-
查看數(shù)據(jù)庫版本
mysql>SELECT VERSION(); version() ----------- 5.5.40
-
查看默認查詢緩存模式
mysql>SHOW VARIABLES LIKE 'query_cache_type'; Variable_name Value ---------------- -------- query_cache_type ON
-
查詢命中情況
mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15711208 Qcache_hits 0 Qcache_inserts 0 Qcache_lowmem_prunes 0 Qcache_not_cached 2 Qcache_queries_in_cache 0 Qcache_total_blocks 1
-
執(zhí)行三次計數(shù)查詢語句以及兩次查詢命中情況
① mysql>SELECT COUNT(*) FROM shop.`shop_user`; count(*) ---------- 1 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15709672 Qcache_hits 0 Qcache_inserts 1 Qcache_lowmem_prunes 0 Qcache_not_cached 3 Qcache_queries_in_cache 1 Qcache_total_blocks 4 ② mysql>SELECT COUNT(*) FROM shop.`shop_user`; count(*) ---------- 1 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15709672 Qcache_hits 1 Qcache_inserts 1 Qcache_lowmem_prunes 0 Qcache_not_cached 4 Qcache_queries_in_cache 1 Qcache_total_blocks 4 ③ mysql>SELECT COUNT(*) FROM shop.`shop_user`; count(*) ---------- 1 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15709672 Qcache_hits 2 Qcache_inserts 1 Qcache_lowmem_prunes 0 Qcache_not_cached 5 Qcache_queries_in_cache 1 Qcache_total_blocks 4
分析:第一次查詢Qcache_inserts的值1,表示1次未命中緩存然后插入瓜贾,意思是新來的SQL請求如果在緩存中未找到诺祸,不得不執(zhí)行查詢處理,執(zhí)行查詢處理后把結(jié)果insert到查詢緩存中祭芦。
最后一次查詢Qcache_hits為2筷笨,表示有2次命中緩存
-
更新當(dāng)前表
mysql>INSERT INTO shop.`shop_user`(PASSWORD,telephone,username)VALUE('123456', '15552424710','Tod'); 1 queries executed, 1 success, 0 errors, 0 warnings mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15711208 Qcache_hits 2 Qcache_inserts 1 Qcache_lowmem_prunes 0 Qcache_not_cached 5 Qcache_queries_in_cache 0 Qcache_total_blocks 1
-
執(zhí)行兩次次基數(shù)查詢并查詢命中情況
① mysql>SELECT COUNT(*) FROM shop.`shop_user`; count(*) ---------- 2 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15709672 Qcache_hits 2 Qcache_inserts 2 Qcache_lowmem_prunes 0 Qcache_not_cached 6 Qcache_queries_in_cache 1 Qcache_total_blocks 4 ② mysql>SELECT COUNT(*) FROM shop.`shop_user`; count(*) ---------- 2 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15709672 Qcache_hits 3 Qcache_inserts 2 Qcache_lowmem_prunes 0 Qcache_not_cached 7 Qcache_queries_in_cache 1 Qcache_total_blocks 4
分析:如果存在對該表插入,其查詢緩存立即失效
-
更新其他表數(shù)據(jù)
mysql>INSERT INTO shop.`shop_product`(pname,pprice,stock) VALUE('魅族',4000.0,5000); 1 queries executed, 1 success, 0 errors, 0 warnings mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15709672 Qcache_hits 3 Qcache_inserts 3 Qcache_lowmem_prunes 0 Qcache_not_cached 7 Qcache_queries_in_cache 1 Qcache_total_blocks 4
-
執(zhí)行一次基數(shù)查詢并查詢命中情況
mysql>SELECT COUNT(*) FROM shop.`shop_user`; count(*) ---------- 2 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15709672 Qcache_hits 4 Qcache_inserts 3 Qcache_lowmem_prunes 0 Qcache_not_cached 8 Qcache_queries_in_cache 1 Qcache_total_blocks 4
分析:其他表的更新對于原查詢不會有影響
結(jié)論
- 查詢緩存的失效只針對當(dāng)前表的更新操作
- 如果當(dāng)前表涉及更新操作龟劲,再此查詢會執(zhí)行緩存插入操作
3.2查詢緩存模式為DEMAND
-
在my.ini文件中添加
# 查詢緩存模式: # 0 : OFF 關(guān)閉 # 1 : ON 緩存所有結(jié)果胃夏,除非select語句使用SQL_NO_CACHE禁用查詢緩存 # 2 : DEMAND 只緩存select語句中通過SQL_CACHE指定需要緩存的查詢 query_cache_type=2
-
重啟數(shù)據(jù)庫服務(wù)
cmd>net restart mysql
-
查看查詢緩存模式
mysql>SHOW VARIABLES LIKE 'query_cache_type'; Variable_name Value ---------------- -------- query_cache_type DEMAND
-
查看命中情況
mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15711208 Qcache_hits 0 Qcache_inserts 0 Qcache_lowmem_prunes 0 Qcache_not_cached 0 Qcache_queries_in_cache 0 Qcache_total_blocks 1
-
執(zhí)行兩次計數(shù)查詢語句以及兩次查詢命中情況
① mysql>SELECT COUNT(*) FROM shop.`shop_user`; count(*) ---------- 2 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15711208 Qcache_hits 0 Qcache_inserts 0 Qcache_lowmem_prunes 0 Qcache_not_cached 2 Qcache_queries_in_cache 0 Qcache_total_blocks 1 ② mysql>SELECT COUNT(*) FROM shop.`shop_user`; count(*) ---------- 2 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15711208 Qcache_hits 0 Qcache_inserts 0 Qcache_lowmem_prunes 0 Qcache_not_cached 4 Qcache_queries_in_cache 0 Qcache_total_blocks 1
-
執(zhí)行兩次顯示指定執(zhí)行查詢緩存模式,執(zhí)行一次普通計數(shù)查詢
① mysql>SELECT SQL_CACHE COUNT(*) FROM shop.`shop_user`; count(*) ---------- 2 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15709672 Qcache_hits 0 Qcache_inserts 1 Qcache_lowmem_prunes 0 Qcache_not_cached 5 Qcache_queries_in_cache 1 Qcache_total_blocks 4 ② mysql>SELECT SQL_CACHE COUNT(*) FROM shop.`shop_user`; count(*) ---------- 2 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15709672 Qcache_hits 1 Qcache_inserts 1 Qcache_lowmem_prunes 0 Qcache_not_cached 6 Qcache_queries_in_cache 1 Qcache_total_blocks 4 ③ mysql>SELECT COUNT(*) FROM shop.`shop_user`; count(*) ---------- 2 mysql>SHOW GLOBAL STATUS LIKE '%Qcache%'; Variable_name Value ----------------------- ---------- Qcache_free_blocks 1 Qcache_free_memory 15709672 Qcache_hits 1 Qcache_inserts 1 Qcache_lowmem_prunes 0 Qcache_not_cached 8 Qcache_queries_in_cache 1 Qcache_total_blocks 4
分析:如果沒有顯式使用
SQL_CACHE
咸灿,即使是同一查詢語句也不走查詢緩存模式
結(jié)論
- 顯式使用
SQL_CACHE
能夠有效控制查詢語句是否走查詢緩存模式构订,能夠人為實現(xiàn)控制。 - 不走查詢緩存模式能夠減少一次寫緩存操作避矢。
MySQL 8.0 版本直接將查詢緩存的整塊功能刪掉了悼瘾,也就是說 8.0 開始徹底沒有這個功能了。