MySQL Query Cache 可將 SELECT 查詢結果快取在記憶體中,相同查詢直接回傳結果,大幅降低 CPU 與 I/O。本文涵蓋兩種啟用方式、關鍵參數配置、命中率驗證、碎片整理與效能調優公式。
Windows: my.ini / Linux: my.cnf
[mysqld]
query_cache_type = 1
query_cache_size = 600000 -- 600KB 起步,生產建議 64MB-256MB
SET GLOBAL query_cache_type = 1;
SET GLOBAL query_cache_size = 600000;
若報錯 query cache is disabled; restart the server with query_cache_type=1,需改設定檔重啟。
SHOW VARIABLES LIKE '%query_cache%';
SHOW STATUS LIKE 'Qcache_hits';
mysql> SET GLOBAL query_cache_size = 600000;
mysql> SET SESSION query_cache_type = ON;
mysql> USE test;
mysql> SELECT COUNT(*) FROM animals; -- 首次查詢
+----------+
| count(*) |
+----------+
| 6 |
+----------+
mysql> SHOW STATUS LIKE 'Qcache_hits'; -- 0 次命中
mysql> SELECT COUNT(*) FROM animals; -- 二次查詢
mysql> SHOW STATUS LIKE 'Qcache_hits'; -- 1 次命中(直接從快取回傳)
mysql> INSERT INTO animals VALUES (9, 'testsds'); -- 寫入操作
mysql> SELECT COUNT(*) FROM animals; -- 快取失效,重新查表
mysql> SHOW STATUS LIKE 'Qcache_hits'; -- 仍為 1(未命中)
寫入操作會自動使相關表的快取失效。
| 參數 | 說明 | 建議值 |
|---|---|---|
query_cache_type | 0=OFF, 1=ON, 2=DEMAND(需 SQL_CACHE 提示) | 1 或 2 |
query_cache_size | 快取總記憶體大小,0 表示關閉 | 64M-256M,視記憶體而定 |
query_cache_limit | 單一查詢結果最大快取大小,超過不快取 | 1M-4M,避免大結果佔滿快取 |
query_cache_min_res_unit | 快取區塊最小單位,預設 4KB | 小查詢多調小,大查詢多調大 |
query_cache_wlock_invalidate | 寫鎖定時是否失效快取 | OFF |
SHOW STATUS LIKE 'Qcache%';
| 變數 | 含義 |
|---|---|
Qcache_free_blocks | 空閒區塊數 |
Qcache_free_memory | 空閒記憶體總量 |
Qcache_hits | 命中次數(累計) |
Qcache_inserts | 插入快取次數(未命中) |
Qcache_lowmem_prunes | 記憶體不足淘汰舊快取次數 |
Qcache_not_cached | 未快取查詢數(無法快取或設定不快取) |
Qcache_queries_in_cache | 目前快取查詢數量 |
Qcache_total_blocks | 總區塊數 |
-- 碎片率:超過 20% 需 FLUSH QUERY CACHE 或調小 min_res_unit
碎片率 = Qcache_free_blocks / Qcache_total_blocks * 100%
-- 利用率:< 25% 過大,> 80% 且 Lowmem_prunes > 50 過小
利用率 = (query_cache_size - Qcache_free_memory) / query_cache_size * 100%
-- 命中率:越高越好,寫入頻繁時偏低屬正常
命中率 = (Qcache_hits - Qcache_inserts) / Qcache_hits * 100%
-- 或簡化:Qcache_hits / (Qcache_hits + Com_select)
NOW()、RAND()、UUID() 等非確定性函數的查詢不會快取SQL_NO_CACHE 強制不快取:SELECT SQL_NO_CACHE * FROM tDEMAND 模式下需显式加 SQL_CACHE:SELECT SQL_CACHE * FROM t