[mysqld]
query_cache_type = 1 # 1=開啟, 0=關閉, 2=按需 (DEMAND)
query_cache_size = 256M # 緩存總大小
query_cache_limit = 2M # 單查詢結果上限
版本警告:MySQL 5.7.20 开始標記棄用,8.0 **完全移除**。生產環境建議改用 **Redis/ProxySQL** 等外部快取層。
SELECT * FROM t ≠ select * from tNOW()、RAND()、UUID()、CONNECTION_ID()-- 強制不使用緩存
SELECT SQL_NO_CACHE * FROM huge_table WHERE ...;
-- 僅特定查詢使用 (query_cache_type=2 時)
SELECT SQL_CACHE * FROM lookup_table WHERE ...;
優化器估算「掃描行數 / 總行數」> **~30%** 時,傾向**放棄索引改走全表掃描**,因為隨機 IO 成本超過順序掃描。
-- 例:SALES 表 100 萬行,滿足條件 60 萬行
SELECT AVG(price) FROM sales WHERE sale_date BETWEEN '2004-01-01' AND '2005-12-31';
-- 優化器可能選擇全表掃描而非 sale_date 索引
**應對**:強制索引 FORCE INDEX (idx_sale_date)、調整統計資訊 ANALYZE TABLE、或改寫查詢邏輯。
鐵律:MySQL 單查詢**最多使用一個索引** (5.6+ 引入 Index Merge 但受限)。
-- 問題:WHERE 用 name 索引,ORDER BY sale_date 無索引 → filesort
SELECT * FROM sales WHERE name='John' ORDER BY sale_date DESC;
-- 解法:複合索引覆蓋 WHERE + ORDER BY
ALTER TABLE sales DROP INDEX idx_name, ADD INDEX idx_name_saledate (name, sale_date);
-- 注意:WHERE 不能包含 sale_date,否則索引順序錯位
EXPLAIN SELECT * FROM sales WHERE name='A' AND name='B';
-- type: NULL, Extra: Impossible WHERE
-- 優化器直接判定無結果,table=NULL,零掃描
其他觸發場景:WHERE 1=0、WHERE id < 10 AND id > 20、WHERE NOT (col IS NULL OR col IS NOT NULL)。
Using indexWHERE date >= '2024-01-01' AND date < '2024-02-01' 而非函數包裹long_query_time=1、log_queries_not_using_indexes=ON,配合 pt-query-digest 分析