查詢緩存存儲SELECT查詢的文本以及發(fā)送給客戶端的相應(yīng)結(jié)果。如果隨后收到一個相同的查詢,,服務(wù)器從查詢緩存中重新得到查詢結(jié)果,,而不再需要解析和執(zhí)行查詢。 如果你有一個不經(jīng)常改變的表并且服務(wù)器收到該表的大量相同查詢,,查詢緩存在這樣的應(yīng)用環(huán)境中十分有用,。對于許多Web服務(wù)器來說存在這種典型情況,它根據(jù)數(shù)據(jù)庫內(nèi)容生成大量的動態(tài)頁面,。 注釋:查詢緩存不返回舊的數(shù)據(jù),。當(dāng)表更改后,查詢緩存值的相關(guān)條目被清空,。 注釋:如果你有許多mysqld服務(wù)器更新相同的MyISAM表,,在這種情況下查詢緩存不起作用,。 注釋:查詢緩存不適用于服務(wù)器方編寫的語句。如果正在使用服務(wù)器方編寫的語句,,要考慮到這些語句將不會應(yīng)用查詢緩存,。 下面是查詢緩存的一些性能數(shù)據(jù)。這些結(jié)果是在Linux Alpha 2 x 500MHz系統(tǒng)(2GB RAM,,64MB查詢緩存)上運行MySQL基準(zhǔn)組件產(chǎn)生的,。 · 如果執(zhí)行的所有查詢是簡單的(如從只有一行數(shù)據(jù)的表中選取一行),但查詢是不同的,,查詢不能被緩存,,查詢緩存激活率是13%。這可以看作是最壞的情形,。在實際應(yīng)用中,,查詢要復(fù)雜得多,因此,,查詢緩存使用率一般會很低,。 · 從只有一行的表中查找一行數(shù)據(jù)時,使用查詢緩存比不使用速度快238%,。這可以看作查詢使用緩存時速度提高最小的情況,。 服務(wù)器啟動時要禁用查詢緩存,設(shè)置query_cache_size系統(tǒng)變量為0,。禁用查詢緩存代碼后,,沒有明顯的速度提高。編譯MySQL時,,通過在configure中使用--without-query-cache選項,,可以從服務(wù)器中徹底去除查詢緩存能力。 本節(jié)描述查詢緩存的工作原理,。 查詢解析之前進(jìn)行比較,,因此下面的兩個查詢被查詢緩存認(rèn)為是不相同的: SELECT * FROM tbl_name Select * from tbl_name 查詢必須是完全相同的(逐字節(jié)相同)才能夠被認(rèn)為是相同的。另外,,同樣的查詢字符串由于其它原因可能認(rèn)為是不同的,。使用不同的數(shù)據(jù)庫、不同的協(xié)議版本或者不同 默認(rèn)字符集的查詢被認(rèn)為是不同的查詢并且分別進(jìn)行緩存,。 從查詢緩存中提取一個查詢之前,,MySQL檢查用戶對所有相關(guān)數(shù)據(jù)庫和表的SELECT權(quán)限。如果沒有權(quán)限,,不使用緩存結(jié)果,。 如果從查詢緩存中返回一個查詢結(jié)果,服務(wù)器把Qcache_hits狀態(tài)變量的值加一,而不是Com_select變量,。 如果一個表被更改了,,那么使用那個表的所有緩沖查詢將不再有效,并且從緩沖區(qū)中移出,。這包括那些映射到改變了的表的使用MERGE表的查詢,。一個表可以被許多類型的語句更改,例如INSERT,、UPDATE,、DELETE、TRUNCATE,、ALTER TABLE、DROP TABLE或DROP DATABASE,。 COMMIT執(zhí)行完后,,被更改的事務(wù)InnoDB表不再有效。 使用InnoDB表時,,查詢緩存也在事務(wù)中工作,,使用該表的版本號來檢測其內(nèi)容是否仍舊是當(dāng)前的。 在MySQL 5.1中,,視圖產(chǎn)生的查詢被緩存,。 SELECT SQL_CALC_FOUND_ROWS ...和SELECT FOUND_ROWS() type類型的查詢使用查詢緩存。即使因創(chuàng)建的行數(shù)也被保存在緩沖區(qū)內(nèi),,前面的查詢從緩存中提取,,F(xiàn)OUND_ROWS()也返回正確的值。 如果一個查詢包含下面函數(shù)中的任何一個,,它不會被緩存:
在下面的這些條件下,,查詢也不會被緩存: · 引用自定義函數(shù)(UDFs)。 · 引用自定義變量,。 · 引用mysql系統(tǒng)數(shù)據(jù)庫中的表,。 · 下面方式中的任何一種: SELECT ...IN SHARE MODE SELECT ...FOR UPDATE SELECT ...INTO OUTFILE ... SELECT ...INTO DUMPFILE ... SELECT * FROM ...WHERE autoincrement_col IS NULL 最后一種方式不能被緩存是因為它被用作為ODBC工作區(qū)來獲取最近插入的ID值。 · 被作為編寫好的語句,,即使沒有使用占位符,。例如,下面使用的查詢: char *my_sql_stmt = "SELECT a,,b FROM table_c"; /* ...*/ mysql_stmt_prepare(stmt,,my_sql_stmt,strlen(my_sql_stmt)); 不被緩存,。 · 使用TEMPORARY表,。 · 不使用任何表。 · 用戶有某個表的列級權(quán)限。 通過have_query_cache服務(wù)器系統(tǒng)變量指示查詢緩存是否可用: mysql> SHOW VARIABLES LIKE 'have_query_cache'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | have_query_cache | YES | +------------------+-------+ 即使禁用查詢緩存,,當(dāng)使用標(biāo)準(zhǔn) MySQL二進(jìn)制時,,這個值總是YES。 其它幾個系統(tǒng)變量控制查詢緩存操作,。當(dāng)啟動mysqld時,,這些變量可以在選項文件或者命令行中設(shè)置。所有查詢緩存系統(tǒng)變量名以query_cache_ 開頭,。 為了設(shè)置查詢緩存大小,,設(shè)置query_cache_size系統(tǒng)變量。設(shè)置為0表示禁用查詢緩存,。 默認(rèn)緩存大小設(shè)置為0,;也就是禁用查詢緩存。 當(dāng)設(shè)置query_cache_size變量為非零值時,,應(yīng)記住查詢緩存至少大約需要40KB來分配其數(shù)據(jù)結(jié)構(gòu),。(具體大小取決于系統(tǒng)結(jié)構(gòu))。如果你把該值設(shè)置的太小,,將會得到一個警告,,如本例所示: mysql> SET GLOBAL query_cache_size = 40000; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> SHOW WARNINGS\G *************************** 1. row *************************** Level: Warning Code: 1282 Message: Query cache failed to set size 39936; new query cache size is 0 mysql> SET GLOBAL query_cache_size = 41984; Query OK, 0 rows affected (0.00 sec) mysql> SHOW VARIABLES LIKE 'query_cache_size'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | query_cache_size | 41984 | +------------------+-------+ 如果查詢緩存大小設(shè)置為大于0,query_cache_type變量影響其工作方式,。這個變量可以設(shè)置為下面的值: · 0或OFF將阻止緩存或查詢緩存結(jié)果,。 · 1或ON將允許緩存,以SELECT SQL_NO_CACHE開始的查詢語句除外,。 · 2或DEMAND,,僅對以SELECT SQL_CACHE開始的那些查詢語句啟用緩存。 設(shè)置query_cache_type變量的GLOBAL值將決定更改后所有連接客戶端的緩存行為,。具體客戶端可以通過設(shè)置query_cache_type變量的會話值控制它們本身連接的緩存行為,。例如,一個客戶可以禁用自己的查詢緩存,,方法如下: mysql> SET SESSION query_cache_type = OFF; 要控制可以被緩存的具體查詢結(jié)果的最大值,,應(yīng)設(shè)置query_cache_limit變量。 默認(rèn)值是1MB,。 當(dāng)一個查詢結(jié)果(返回給客戶端的數(shù)據(jù))從查詢緩沖中提取期間,,它在查詢緩存中排序。因此,,數(shù)據(jù)通常不在大的數(shù)據(jù)塊中處理,。查詢緩存根據(jù)數(shù)據(jù)排序要求分配數(shù)據(jù)塊,,因此,當(dāng)一個數(shù)據(jù)塊用完后分配一個新的數(shù)據(jù)塊,。因為內(nèi)存分配操作是昂貴的(費時的),,所以通過query_cache_min_res_unit系統(tǒng)變量給查詢緩存分配最小值。當(dāng)查詢執(zhí)行時,,最新的結(jié)果數(shù)據(jù)塊根據(jù)實際數(shù)據(jù)大小來確定,,因此可以釋放不使用的內(nèi)存。根據(jù)你的服務(wù)器執(zhí)行查詢的類型,,你會發(fā)現(xiàn)調(diào)整query_cache_min_res_unit變量的值是有用的: · query_cache_min_res_unit默認(rèn)值是4KB,。這應(yīng)該適合大部分情況。 · 如果你有大量返回小結(jié)果數(shù)據(jù)的查詢,,默認(rèn)數(shù)據(jù)塊大小可能會導(dǎo)致內(nèi)存碎片,,顯示為大量空閑內(nèi)存塊。由于缺少內(nèi)存,,內(nèi)存碎片會強(qiáng)制查詢緩存從緩存內(nèi)存中修整(刪除)查詢,。這時,你應(yīng)該減少query_cache_min_res_unit變量的值,。空閑塊和由于修整而移出的查詢的數(shù)量通過Qcache_free_blocks和Qcache_lowmem_prunes變量的值給出,。 · 如果大量查詢返回大結(jié)果(檢查 Qcache_total_blocks和Qcache_queries_in_cache狀態(tài)變量),,你可以通過增加query_cache_min_res_unit變量的值來提高性能。但是,,注意不要使它變得太大(參見前面的條目),。 可以使用下面的語句檢查MySQL服務(wù)器是否提供查詢緩存功能: mysql> SHOW VARIABLES LIKE 'have_query_cache'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | have_query_cache | YES | +------------------+-------+ 可以使用FLUSH QUERY CACHE語句來清理查詢緩存碎片以提高內(nèi)存使用性能。該語句不從緩存中移出任何查詢,。 RESET QUERY CACHE語句從查詢緩存中移出所有查詢,。FLUSH TABLES語句也執(zhí)行同樣的工作。 為了監(jiān)視查詢緩存性能,,使用SHOW STATUS查看緩存狀態(tài)變量: mysql> SHOW STATUS LIKE 'Qcache%'; +-------------------------+--------+ |變量名 |值 | +-------------------------+--------+ | Qcache_free_blocks | 36 | | Qcache_free_memory | 138488 | | Qcache_hits | 79570 | | Qcache_inserts | 27087 | | Qcache_lowmem_prunes | 3114 | | Qcache_not_cached | 22989 | | Qcache_queries_in_cache | 415 | | Qcache_total_blocks | 912 | +-------------------------+--------+ 這里描述它們的一些應(yīng)用,。 SELECT查詢的總數(shù)量等價于: Com_select + Qcache_hits + queries with errors found by parser Com_select的值等價于: Qcache_inserts + Qcache_not_cached + queries with errors found during columns/rights check 查詢緩存使用長度可變塊,因此Qcache_total_blocks和Qcache_free_blocks可以顯示查詢緩存內(nèi)存碎片,。執(zhí)行FLUSH QUERY CACHE后,,只保留一個空閑塊。 每個緩存查詢至少需要兩個塊(一個塊用于查詢文本,,一個或多個塊用于查詢結(jié)果),。并且,每一個查詢使用的每個表需要一個塊,。但是,,如果兩個或多個查詢使用相同的表,,僅需要分配一個塊。 Qcache_lowmem_prunes狀態(tài)變量提供的信息能夠幫助你你調(diào)整查詢緩存的大小,。它計算為了緩存新的查詢而從查詢緩沖區(qū)中移出到自由內(nèi)存中的查詢的數(shù)目,。查詢緩沖區(qū)使用最近最少使用(LRU)策略來確定哪些查詢從緩沖區(qū)中移出。 |
|