| 問題類型 | 現象 | 解決方案 |
|---|---|---|
| 過度查詢 | 需 10 筆卻 SELECT 100 筆再 LIMIT | 精確 SELECT 欄位,避免 SELECT * |
| 多表關聯全欄位 | JOIN 時返回所有表所有欄位 | 明確列出所需欄位 |
| 重複查詢 | 同一頁多次查用戶頭像 URL | 應用層快取 (Redis/本地快取) |
MySQL 內存掃描百萬行極快,但網傳結果給客戶端較慢。適度拆分大查詢為多個小查詢,減少單次傳輸量與鎖持有時間。
-- 原始:單次刪除 3 個月前資料,可能鎖表許久
DELETE FROM messages WHERE created < DATE_SUB(NOW(), INTERVAL 3 MONTH);
-- 優化:分批刪除,每批 1000 筆,間隔休眠
ROWS_AFFECTED=0;
DO {
ROWS_AFFECTED = EXECUTE(
"DELETE FROM messages WHERE created < DATE_SUB(NOW(), INTERVAL 3 MONTH) LIMIT 1000"
);
SLEEP(0.05); -- 50ms 釋放鎖讓其他查詢進入
} WHILE ROWS_AFFECTED > 0;
適用場景:應用可快取單表結果、跨庫分佈、可用 IN() 替代 JOIN、單表主導查詢
-- 深分頁優化:延遲關聯 SELECT * FROM t WHERE id >= (SELECT id FROM t ORDER BY id LIMIT 1000000, 1) LIMIT 10; -- 主鍵範圍分頁 (最佳) SELECT * FROM t WHERE id > 1000000 AND id <= 1001000;