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

MySQL Query Cache 關鍵誤區:鍵值包含 Database/Flag、前導空格不影響命中

     編輯:MySQL 資料庫相關知識

流傳誤區

網上常見說法:「SQL 前後有空格會導致 Query Cache 未命中,視為不同查詢」。**此說法不嚴謹。**

實測驗證

  1. 開啟 QC:SET GLOBAL query_cache_type=ON; SET GLOBAL query_cache_size=67108864;
  2. 執行 SELECT * FROM t WHERE id=1; → Qcache_inserts=1
  3. 執行 SELECT * FROM t WHERE id=1; (前導空格) → Qcache_hits=1, inserts 不變

結論:前導空格**不影響**命中。

源碼級解析 (MySQL 5.1)

入口:dispatch_command()

bool alloc_query(THD *thd, const char *packet, uint packet_length) {
  // 1. 移除開頭空白
  while (packet_length > 0 && my_isspace(thd->charset(), packet[0])) {
    packet++; packet_length--;
  }
  // 2. 移除結尾 ; 和空白
  const char *pos = packet + packet_length;
  while (packet_length > 0 && (pos[-1] == ';' || my_isspace(thd->charset(), pos[-1]))) {
    pos--; packet_length--;
  }
  // 3. 複製到查詢緩衝區 (含 db_name、flags)
  ...
}

關鍵點:alloc_query 在構建查詢緩衝區**前**已完成 TrimLeft/TrimRight,因此前導/尾隨空格、分號均被標準化。

Query Cache Key 組成

Key = normalized_query_string + current_database + client_flags
  • normalized_query_string:經 alloc_query 處理後的標準化 SQL。
  • current_database:當前默認庫 (影響同 SQL 不同庫語義)。
  • client_flags:包含 SQL_MODE、字符集等影響執行結果的標誌位。

真正導致未命中的空格情況

**SQL 中間** 的多餘空格:SELECT * FROM t vs SELECT * FROM t → 視為不同 Key (中間空格未被標準化)。

最佳實踐建議

  1. 應用層統一 SQL 格式化 (去除多餘空格、統一大小寫、固定關鍵字順序)。
  2. 啟用 QC 時,監控 Qcache_hits / (Qcache_hits + Qcache_inserts) 命中率,低於 20% 考慮關閉。
  3. 高併發寫入場景 (頻繁失效) 建議關閉 QC,改用 Redis/Memcached 應用層緩存。
  4. MySQL 8.0 已**移除 Query Cache**,遷移時請評估替代方案。

結語

Query Cache 鍵值機制經過標準化處理,**前導/尾隨空格無影響,中間空格有影響**,且 Key 包含庫名與 Flags。理解底層機制,避免盲目優化,並在 8.0 時代平滑遷移至應用層緩存架構。

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