原理:相同 SELECT 直接返回快取結果,零解析、零執行。
-- 失效寫法 (函數、非確定性)
SELECT * FROM users WHERE signup_date >= CURDATE();
-- 生效寫法 (固定值)
$today = date('Y-m-d');
SELECT * FROM users WHERE signup_date >= '$today';
⚠️ MySQL 8.0 已移除 Query Cache,改用 ProxySQL 快取、Redis 應用層快取、Prepared Statement 重用執行計畫。
EXPLAIN SELECT * FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 'paid' AND u.city = 'Taipei';
| 欄位 | 理想值 | 異常值處理 |
|---|---|---|
| type | ref / eq_ref / range | ALL (全表掃描) → 加索引 |
| key | 實際用到的索引名 | NULL → 無索引可用 |
| rows | 預估掃描行數越少越好 | 巨大 → 條件/索引優化 |
| Extra | Using index (覆蓋索引) | Using filesort/temporary → 優化 ORDER BY/GROUP BY |
-- 低效
SELECT * FROM users WHERE city = 'Taipei';
IF (mysqli_num_rows($r) > 0) ...
-- 高效
SELECT 1 FROM users WHERE city = 'Taipei' LIMIT 1;
-- 引擎命中第一行即停止,不掃描全表
INDEX (a,b,c) 支援 a、a,b、a,b,cSELECT a,b FROM t WHERE c=1 + INDEX (c,a,b) → Extra: Using index,無需回表-- 低效:型別不匹配導致隱式轉換、索引失效
SELECT * FROM users u
JOIN orders o ON u.phone = o.user_phone; -- u.phone VARCHAR(20), o.user_phone CHAR(11)
-- 高效:統一型別、長度、字元集
ALTER TABLE orders MODIFY user_phone VARCHAR(20) CHARSET utf8mb4;
-- 或建立函數索引 (8.0+) / 生成欄位
| 工具 | 定位 | 特色 |
|---|---|---|
| Percona Toolkit (pt-query-digest) | 慢查詢分析 | 聚合、排序、抽樣、報表生成 |
| sys Schema (sys.* views) | 內建診斷 | 8.0 內建、statement 分析、IO、鎖、等待 |
| MySQL Workbench Performance Dashboard | 圖形化監控 | 即時 QPS、緩衝區命中、鎖等待 |
| Prometheus + mysqld_exporter + Grafana | 生產監控 | 全指標採集、告警、儀表板 |
| GH-OST / pt-online-schema-change | Online DDL | 無鎖結構變更、可暫停/限流 |
調優無銀彈,只有觀測 → 定位 → 驗證 → 沉澱閉環。將五大技巧內化為代碼審查清單,配合工具鏈持續巡檢,效能問題才能在發酵前被消滅。