「Query Cache 的 Key 是完整 SQL 文本,多一個空格就會 Miss」——不完全正確。
實測證實:SQL 前導空格會被 dispatch_command() → alloc_query() 自動去除,因此 " SELECT 1" 與 "SELECT 1" 命中同一 Cache。但 SQL 中間的空格、大小寫、註解差異仍會導致 Miss。
Normalized SQL + Default Database + Client Character Set + Flags(非單純 SQL 文本)。| 參數 | 預設 | 建議 | 說明 |
|---|---|---|---|
query_cache_type | ON (1) | DEMAND (2) | 0=關閉、1=全開、2=需 SQL_CACHE 提示才緩存 |
query_cache_size | 0 (關閉) | 64M~256M | 總記憶體,須 1024 倍數;超過 256M 通常得不償失 |
query_cache_limit | 1M | 1M~4M | 單次結果集超過此值不緩存 |
query_cache_min_res_unit | 4KB | 1K~4K | 記憶體分配最小單位,過大造成碎片 |
query_cache_wlock_invalidate | OFF (0) | ON (1) | 寫鎖時是否立即失效該表 Cache |
| ✅ 適合 | ❌ 不適合 |
|---|---|
| 讀多寫極少(如配置表、字典表、靜態內容) | 高頻寫入表(訂單、日誌、計數器) |
| 相同 SQL 重複執行率高 | SQL 參數化差、動態條件多 |
| 結果集較小(< 1M) | 大結果集(報表、導出) |
SHOW GLOBAL STATUS LIKE 'Qcache%';
| 指標 | 含義 | 健康判斷 |
|---|---|---|
Qcache_hits | 命中次數 | 持續增長為佳 |
Qcache_inserts | 新增 Cache 次數 | 與 Hits 比值反映命中率 |
Qcache_lowmem_prunes | 因記憶體不足淘汰舊 Cache 次數 | 頻繁增長 → 擴大 query_cache_size 或關閉 |
Qcache_free_memory | 剩餘記憶體 | 過低 → 擴容;過高 → 浪費 |
Qcache_free_blocks | 空閒 Block 數 | 碎片化指標 |
Qcache_queries_in_cache | 當前缓存查詢數 | 配合 free_blocks 看碎片率 |
Hit Rate = Qcache_hits / (Qcache_hits + Qcache_inserts) * 100%
SQL_CACHE。lowmem_prunes。8.0 官方移除 Query Cache,理由:
1. 單一全域鎖在高併發下成為瓶頸。
2. 失效機制粗暴,寫入頻繁時命中率極低。
3. 應用層快取更靈活。
遷移建議:改用 Redis/Memcached、ProxySQL Query Cache、或應用層本地快取(Caffeine、Guava Cache)。