首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 查詢快取深度優化:原理、配置、監控指標、碎片整理與適用場景全解析

     編輯:MySQL 資料庫相關知識

查詢快取 (Query Cache, QC) 運作原理

MySQL 4.0+ 引入,將 SELECT 查詢文本 (經正規化) 與結果集 以 Key-Value 形式存入記憶體。後續完全相同的查詢 (含大小寫、空格、註解) 直接返回快取結果,繞過解析、優化、執行、存儲引擎層。

關鍵限制:

  • 任何表的寫入 (INSERT/UPDATE/DELETE/TRUNCATE/ALTER) 會使該表相關所有快取失效
  • 不支援預處理語句、存儲函數、觸發器、事件、系統表、臨時表、SQL_NO_CACHE、CURRENT_DATE()/NOW()/RAND() 等非確定性函數
  • 結果集大小超過 query_cache_limit 不快取
  • MySQL 5.7.20 棄用,8.0 完全移除 (官方建議改用 ProxySQL/Redis/應用層快取)

適用性判斷:什麼時候開、什麼時候關?

場景特徵QC 效果建議
讀多寫少 (95%+ SELECT)、重複查詢率高、資料變更頻率低極佳,命中率 80%+開啟,適度分配記憶體
寫入頻繁、表較小、查詢模式多變負效能 (失效開銷 > 命中收益)關閉 (query_cache_type=0, query_cache_size=0)
大結果集、Blob/Text 多記憶體壓力大、碎片嚴重關閉或極小限額
8.0+ 環境不存在遷移至 ProxySQL Query Cache / Redis / 應用層

配置參數詳解

[mysqld]
# 總記憶體上限,0=關閉。建議 64M-512M,不可過大 (鎖爭用)
query_cache_size = 128M

# 單個查詢結果上限,超過不快取。預設 1M,建議 64K-1M
query_cache_limit = 256K

# 分配最小記憶體塊,預設 4K。碎片多時調大 (16K-64K),小結果集調小
query_cache_min_res_unit = 16K

# 快取類型:0=關閉、1=開啟 (預設)、2=按需 (需 SQL_CACHE 提示)
query_cache_type = 1

# 寫入時是否讓快取失效前等待鎖,ON=更安全但有延遲
query_cache_wlock_invalidate = OFF

核心監控指標 (SHOW STATUS LIKE 'Qcache%')

變量含義健康判讀
Qcache_free_memory剩餘可用記憶體接近 0 → 擴容或關閉
Qcache_hits命中次數核心效益指標
Qcache_inserts新增快取條目數寫入頻率
Qcache_lowmem_prunes因記憶體不足被淘汰數持續增長 → 記憶體不足,需擴容或關閉
Qcache_not_cached未快取查詢數 (非確定性/超大/關閉)參考
Qcache_queries_in_cache當前快取查詢數容量利用率
Qcache_total_blocks總記憶體塊數 (含碎片)基線
Qcache_free_blocks空閒記憶體塊數遠大於 1 → 嚴重碎片化,需 FLUSH QUERY CACHE

碎片化成因與整理

成因:MySQL 採用動態記憶體分配,每次分配 query_cache_min_res_unit 大小塊。結果集較小時,塊尾部空間成為碎片;釋放時若相鄰塊也空閒會合併,否則形成碎片。
現象:Qcache_free_blocks 大、Qcache_free_memory 看似充足但無法分配新查詢、Qcache_lowmem_prunes 飆升。
整理:

FLUSH QUERY CACHE;   -- 僅整理碎片,不清除內容,Qcache_free_blocks 變 1
RESET QUERY CACHE;   -- 完全清空快取,慎用

建議:低峰期定時任務每小時執行一次 FLUSH QUERY CACHE。

query_cache_min_res_unit 最優計算公式 (High Performance MySQL)

query_cache_min_res_unit = (query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache

意義:平均每個快取查詢佔用的記憶體。實測調整後可減少 30-50% 碎片塊。

SQL 層控制快取行為

-- 強制不快取 (query_cache_type=1 時)
SELECT SQL_NO_CACHE * FROM large_table WHERE ...;

-- 強制快取 (query_cache_type=2 時)
SELECT SQL_CACHE * FROM hot_table WHERE ...;

-- 關閉會話級快取
SET SESSION query_cache_type = OFF;

遷移指南:MySQL 8.0+ 無 QC 怎麼辦?

方案定位優點缺點
ProxySQL Query Cache中間件層透明無侵入、支援多 MySQL、LRU 淘汰、統計豐富額外元件、單點需 HA
Redis / Memcached應用層 / Sidecar高效能、分散式、資料結構豐富、TTL 精確控制應用需改造、快取一致性自管
應用程式本地快取 (Caffeine/Guava)進程內零網路延遲、極高 QPS多實例不一致、重啟失效、記憶體受限
Materialized View / Summary Table資料庫層資料一致性強、查詢極快維護成本高、非即時

建議:熱點查詢 → ProxySQL QC;複雜聚合 → Summary Table + 定時刷新;Session 級熱點 → 本地快取;分散式服務共享 → Redis。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved