MySQL Reference Manual for version 4.1.0-alpha.


6.9 MySQL 查詢快取

從 MySQL 4.0.1 開始,MySQL server 有一個重要的特征:Query Cache。 當在使用中,查詢快取會儲存一個 SELECT 查詢的純文字與被傳送到客戶端的相應結果。如果之後接收到一個同樣的查詢,伺服器將從查詢快取中檢索結果,而不是再次分析和執行這個同樣的查詢。

注意:查詢快取絕不傳回過期資料。當資料被修改後,在查詢快取中的任何相關詞條均被轉儲清除。

在某些表並不經常變更,而你又對它執行大量的相同查詢時,查詢快取將是非常有用的。對於許多 WEB 伺服器使用大量的動態資訊,這是一個很典型的情況。

下面是查詢快取的一個性能資料。(這些結果的產生,是通過在一個 a Linux Alpha 2 x 500 MHz、2GB RAM 和 64MB 查詢快取上執行 MySQL 基準套件和到的):

6.9.1 查詢快取如何運作

查詢在分析之前先被比較,因而

SELECT * FROM tbl_name

Select * from tbl_name

對於查詢快取被當作是不同的查詢,因而查詢需要嚴格的一致(字節對字節的),才會被認為是同樣的。 另外,如果一個客戶端使用一個新的連線協定格式或不同於其它客戶端的另一個字元集,一個查詢將被視為不同的。

使用不同資料庫的,使用不同協定版本的,或使用不同的預設字串的查詢將被認為是不同的查詢,並將分別的緩衝。

高速緩衝不對 SELECT CALC_ROWS ...SELECT FOUND_ROWS() ... 類型的查詢起作用,因為找到的行的數目也是被儲存在緩衝裡的。

如果查詢結果被從查詢快取中傳回,那麼狀態變數 Com_select 將不會被增加,但是 Qcache_hits 卻會增加。查看章節 6.9.4 查詢快取的狀態和維護

如果一個表發生的改變 (INSERT, UPDATE, DELETE, TRUNCATE, ALTERDROP TABLE|DATABASE),那麼所有這張表使用的緩衝的查詢(可能通過一個 MRG_MyISAM 表!)將被得失效,並從緩衝中移除。

InnoDB 表的事務所做的變更將在一個 COMMIT 被完成時,使資料失效。

如果一個查詢包括下面的函數,它將不能被緩衝:
函數 函數 函數
User-Defined Functions CONNECTION_ID FOUND_ROWS
GET_LOCK RELEASE_LOCK LOAD_FILE
MASTER_POS_WAIT NOW SYSDATE
CURRENT_TIMESTAMP CURDATE CURRENT_DATE
CURTIME CURRENT_TIME DATABASE
ENCRYPT (只有一個參數調用) LAST_INSERT_ID RAND
UNIX_TIMESTAMP (無參數調用) USER BENCHMARK

如果一個查詢包含使用者變數,參照 MySQL 系統資料庫,或下列之一的格式,SELECT ... IN SHARE MODE, SELECT ... INTO OUTFILE ..., SELECT ... INTO DUMPFILE ...SELECT * FROM AUTOINCREMENT_FIELD IS NULL (檢索最後一個插入 ID - ODBC 語句),該查詢亦不可以被快取。

然而,FOUND ROWS() 將傳回正確的值,即使先前的查詢是從快取中讀取的。

萬一一個查詢不使用任何表,或使用臨時表,或使用者對任何相關表有一個列權限,那麼查詢將不會被快取。

在一個查詢從查詢快取中讀取前,MySQL 將檢查使用者對所有相關的資料庫和表有 SELECT 權限。如果不是這種情況,快取的結果將不能被使用。

6.9.2 查詢快取設定

查詢快取為了 mysqld 加入了幾個 MySQL 系統變數,它可以在配置文件中被設定,或在啟動 mysqld 時的命令行上設定。

在一個線程(連線)內,查詢快取的行為可以被改變。句法如下所示:

QUERY_CACHE_TYPE = OFF | ON | DEMAND QUERY_CACHE_TYPE = 0 | 1 | 2

選項 含義
0 or OFF 不快取或重新得到結果
1 or ON 快取所有的結果,除了 SELECT SQL_NO_CACHE ... 查詢
2 or DEMAND 僅快取 SELECT SQL_CACHE ... 查詢

6.9.3 在 SELECT 中的查詢快取選項

有兩個可能的查詢快取相關的參數可以在一個 SELECT 查詢中被指定:

選項 含義
SQL_CACHE 如果 QUERY_CACHE_TYPEDEMAND,允許該查詢被快取。如果 QUERY_CACHE_TYPEON,這是預設的。如果 QUERY_CACHE_TYPEOFF,它不做任何事
SQL_NO_CACHE 使這個查詢不被快取,不允許這個查詢被儲存到高速快取中

6.9.4 查詢快取的狀態和維護

使用 FLUSH QUERY CACHE 命令,你可以整理查詢快取,以更好的利用它的記憶體。這個命令不會從快取中移除任何查詢。FLUSH TABLES 會轉儲清除查詢快取。

RESET QUERY CACHE 使命從查詢快取中移除所有的查詢結果。

你可以檢查查詢快取在你的 MySQL 是否被引進:

mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+
1 row in set (0.00 sec)

SHOW STATUS 中,你可以監視查詢快取的性能:

變數 含義
Qcache_queries_in_cache 在快取中已注冊的查詢數目
Qcache_inserts 被加入到快取中的查詢數目
Qcache_hits 快取取樣數數目
Qcache_lowmem_prunes 因為缺少記憶體而被從快取中刪除的查詢數目
Qcache_not_cached 沒有被快取的查詢數目 (不能被快取的,或由於 QUERY_CACHE_TYPE)
Qcache_free_memory 查詢快取的閒置記憶體總數
Qcache_free_blocks 查詢快取中的閒置記憶體塊的數目
Qcache_total_blocks 查詢快取中的塊的總數目

Total number of queries = Qcache_inserts + Qcache_hits + Qcache_not_cached.

查詢快取使用變長的塊,因而 Qcache_total_blocksQcache_free_blocks 可能顯示查詢快取的碎片。在 FLUSH QUERY CACHE 之後,只有剩餘一個單獨的(大的)閒置塊。

注意:每個查詢最小需要兩個塊(一個用於儲存查詢純文字,另一個或多個用於儲存查詢結果)。同樣的,每個被一個查詢使用的表需要一個塊,但是,如果有兩個或更多的查詢使用同一張表,僅僅只需要分配一個塊就行了。

你可以使用狀態變數 Qcache_lowmem_prunes 來諧調查詢快取尺寸。它計數被從快取中移除的查詢,該查詢的移除是為了釋放記憶體,以快取新增的查詢。查詢快取使用一個 least recently used (LRU) 策略來判斷從快取中移除哪個查詢。