一、概述
MySQL Query Cache 會緩存select 查詢,安裝時默認是開啟的,但是如果對表進行INSERT, UPDATE, DELETE, TRUNCATE, ALTER TABLE, DROP TABLE, or DROP DATABASE等操作時,之前的緩存會無效並且刪除。這樣一定程度上也會影響我們數據庫的性能。所以對一些頻繁的變動表的情況開啟緩存是不明智的。還有一種情況我們測試數據庫性能的時候也要關閉緩存,避免緩存對我們測試數據的影響。
1.1、QueryCache的實現原理;
1、目前只有select語句會被cache,其他類似show,use的語句則不會被cache。
2、兩個SQL語句,只要相差哪怕是一個字符(例如大小寫不一樣;多一個空格等),那么這兩個SQL將使用不同的一個CACHE。
但是會:
- 過濾所有注釋
- 去掉SQL文本前後的空格,TAB等字符。注意,是文本前面和後面的。中間的不會被去掉。
一個被頻繁更新的表如果被應用了QC,可能會加重數據庫的負擔,而不是減輕負擔。一般的做法是默認打開QC,而對一些涉及頻繁更新的表的SQL語句加上SQL_NO_CACHE關鍵詞來對其禁用CACHE。這樣可以盡可能避免不必要的內存操作,盡可能保持內存的連續性。那些查詢很分散的SQL語句,也不應該使用QC。例如用來查詢用戶和密碼的語句——“select pass from user where name='surfchen'”。這樣的語句,在一個系統里,很有可能只在一個用戶登陸的時候被使用。每個用戶的登陸所用到的查詢,都是不一樣的SQL文本,QC在這里就幾乎不起作用了,因為緩存的數據幾乎是不會被用到的,它們只會在內存里占地方。
1.2、QueryCache的負面影響:
1,Query的hash性能問題和命中率問題;
2,查詢緩存及其容易失效;當表內容發生變化或者表結構發生變化,對應的查詢緩存內容都會失效;
3,查詢緩存中的結果容易產生重復;因為查詢緩存中緩存的是查詢結果,所以不同的查詢的結果很容易重復;
1.3、Query Cache的使用:
1,設置query_cache_limit為查詢緩存大小,如果為0,則不使用查詢緩存;
2,使用SQL_CACHE或者SQL_NO_CACHE來強制是否使用查詢緩存;
如, 如果query_cache_type為1而又不想利用查詢緩存中的數據,可以用下面的SQL:
SELECT SQL_NO_CACHE * FROM my_table WHERE condition;
如果值為2,要使用緩存的話,需要使用SQL_CACHE開關參數:
SELECT SQL_CACHE * FROM my_table WHERE condition;
3,查詢查詢緩存設置:show variables like '%query_cache%';
1,“have_query_cache”:該MySQL 是否支持Query Cache;按實際情況YES 或 NO
2,“query_cache_limit”:Query Cache 存放的單條Query 最大Result Set ,默認1M;
3,“query_cache_min_res_unit”:Query Cache 每個Result Set 存放的最小內存大小,默認4k;
4,“query_cache_size”:系統中用於Query Cache 內存的大小;默認為0,表示為查詢緩存預留的內存為0,則無法使用查詢緩存。所以我們需要設置query_cache_size的值:
5,“query_cache_type”:系統是否打開了Query Cache 功能;默認為OFF
開始關閉緩存。關閉緩存有兩種放法,一種臨時的,一種永久的。
臨時的直接再命令行執行
set global query_cache_size=0
set global query_cache_type=0
永久的修改配置文件my.cnf ,添加下面的配置即可。
query_cache_type=0
query_cache_size=0
1.4、 查詢查詢緩存使用情況:show status like 'Qcache%';
1,“Qcache_free_blocks”:Query Cache 中目前還有多少剩余的blocks。如果該值顯示較大,則說明Query Cache 中的內存碎片較多了
2,“Qcache_free_memory”:Query Cache 中目前剩余的內存大小;
3,“Qcache_hits”:多少次命中;
4,“Qcache_inserts”:多少次未命中然后插入;Query Cache 命中率= Qcache_hits / ( Qcache_hits + Qcache_inserts );
5,“Qcache_lowmem_prunes”:多少條Query 因為內存不足而被清除出Query Cache;
6,“Qcache_not_cached”:因為query_cache_type 的設置或者不能被cache 的Query 的數量;
7,“Qcache_queries_in_cache”:當前Query Cache 中cache 的Query 數量;
8,“Qcache_total_blocks”:當前Query Cache 中的block 數量;
1.5、query cache的使用限制:
1,mysql query cache內容為 select 的結果集, cache 使用完整的 sql 字符串做 key, 並區分大小寫,空格等。即兩個sql必須完全一致才會導致cache命中。
2,prepared statement永遠不會cache到結果,即使參數完全一樣,
3,where條件中如包含了某些函數永遠不會被cache, 比如current_date, now等。
4,太大的result set不會被cache (< query_cache_limit)
1.6、query cache的使用方式:
1,如果沒有絕對的使用把握,可以關閉查詢緩存;【其實按照默認配置即可,推薦由DBA統一運維】
2,如果要使用查詢緩存,最好能夠精確的控制那些表內容放到查詢緩存,哪些表不用查詢緩存;
注:存儲塊block說明
QC緩存一個查詢結果的時候,一般情況下不是一次性地分配足夠多的內存來緩存結果的。而是在查詢結果獲得的過程中,逐塊存儲。當一個存儲塊被填滿之後,一個新的存儲塊將會被創建,並分配內存(allocate)。單個存儲塊的內存分配大小通過query_cache_min_res_unit參數控制,默認為4KB。最後一個存儲塊,如果不能被全部利用,那么沒使用的內存將會被釋放。如果被緩存的結果很大,那么會可能會導致分配內存操作太頻繁,系統系能也隨之下降;而如果被緩存的結果都很小,那么可能會導致內存碎片過多,這些碎片如果太小,就很有可能不能再被分配使用。
除了查詢結果需要存儲塊之外,每個SQL文本也需要一個存儲塊,而涉及到的表也需要一個存儲塊(表的存儲塊是所有線程共享的,每個表只需要一個存儲塊)。存儲塊總數量=查詢結果數量*2+涉及的數據庫表數量。也就是說,第一個緩存生成的時候,至少需要三個存儲塊:表信息存儲塊,SQL文本存儲塊,查詢結果存儲塊。而第二個查詢如果用的是同一個表,那么最少只需要兩個存儲塊:SQL文本存儲塊,查詢結果存儲塊。
通過觀察Qcache_queries_in_cache和Qcache_total_blocks可以知道平均每個緩存結果占用的存儲塊。
它們的比例如果接近1:2,則說明當前的query_cache_min_res_unit參數已經足夠大了。
如果Qcache_total_blocks比Qcache_queries_in_cache多很多,則需要增加query_cache_min_res_unit的大小。
Qcache_queries_in_cache*query_cache_min_res_unit(sql文本和表信息所在的block占用的內存很小,可以忽略)如果遠遠大於query_cache_size-Qcache_free_memory,那么可以嘗試減小query_cache_min_res_unit的值。
1.7、排序緩沖
當一個查詢需要對結果進行排序的時候,MySQL會分配一定的內存用來排序。這個內存大小由sort_buffer_size來控制。記得,這個參數是針對每個查詢的,而不是所有查詢總共可分配的量。
如果sort_buffer_size不夠大,排序的結果將會被分段寫入臨時文件里。每次結束之後再把文件中的排序結果拿出來合並,進行再次排序,直到得出最後結果。sort_buffer_size越小,合並的次數就越多。合並次數可以通過狀態變量Sort_merge_passes獲得。理論上,Sort_merge_passes越小,排序越快。但是在實際應用中可能並非如此。sort_buffer_size如何設置需要根據實際運行環境來進行測試。如果實在不知道如何測試,那么就設到使Sort_merge_passes為0吧。
read_buffer_size read_rnd_buffer_size join_buffer_size thread_cache
1.8、字段類型推薦
這條語句可以根據當前表的內容來給出一個字段類型的推薦。
select * from test_table_idx PROCEDURE ANALYSE();
上述參考自:http://blog.csdn.net/iris_xuting/article/details/50495928#t0