類似 Oracle 的 Hint 機制,MySQL 提供多種 Hint 讓開發者干預執行計劃,適用於優化器選擇不佳的場景。
| Hint | 語法 | 作用 |
|---|---|---|
| 強制使用索引 | FORCE INDEX (idx_name) | 只使用指定索引,忽略其他 |
| 忽略索引 | IGNORE INDEX (idx1, idx2) | 不使用列出的索引 |
| 使用索引 | USE INDEX (idx_name) | 建議使用,優化器仍可選擇全表掃描 |
-- 範例:強制走 FIELD1 索引
SELECT * FROM table1 FORCE INDEX (field1) WHERE field1 = 'value';
-- 範例:長時間範圍查詢強制索引可大幅提升效率
SELECT * FROM orders IGNORE INDEX (idx_user) WHERE created_at > '2023-01-01';
| Hint | 語法 | 說明 |
|---|---|---|
| 不使用快取 | SQL_NO_CACHE | 即時查詢、低頻執行 SQL,避免汙染快取 |
| 強制使用快取 | SQL_CACHE | 配合 query_cache_type=2 時生效 |
SELECT SQL_NO_CACHE field1, field2 FROM table1;
SELECT SQL_CACHE * FROM table1;
| Hint | 適用語句 | 效果 |
|---|---|---|
| HIGH_PRIORITY | SELECT, INSERT | 提升優先級,插隊執行 |
| LOW_PRIORITY | INSERT, UPDATE, DELETE | 降低優先級,等待其他讀寫完成 |
| DELAYED | INSERT | 客戶端立即收到 OK,資料暫存記憶體排隊寫入,批次合併提高吞吐,但無法獲取自增 ID,崩潰可能丟資料 |
SELECT HIGH_PRIORITY * FROM table1;
UPDATE LOW_PRIORITY table1 SET field1 = 'val' WHERE id = 1;
INSERT DELAYED INTO table1 SET field1 = 'val';
-- 強制按 table1 → table2 順序 JOIN
SELECT t1.field1, t2.field2
FROM table1 STRAIGHT_JOIN table2
WHERE t1.id = t2.t1_id;
適用於優化器選擇錯誤驅動表導致效能差的場景。
| Hint | 語法 | 適用場景 |
|---|---|---|
| 強制臨時表 | SQL_BUFFER_RESULT | 大結果集,快釋放表鎖,支援長時間傳輸 |
| 大結果集分組 | SQL_BIG_RESULT | GROUP BY/DISTINCT 時直接用磁碟臨時表排序 |
| 小結果集分組 | SQL_SMALL_RESULT | 優先記憶體臨時表(預設行為) |
SELECT SQL_BUFFER_RESULT * FROM table1 WHERE ...;
SELECT SQL_BIG_RESULT field1, COUNT(*) FROM table1 GROUP BY field1;
-- 1. 只需一筆資料加 LIMIT 1
SELECT * FROM table1 WHERE status = 1 LIMIT 1;
-- 2. 固定筆數查詢務必加 ORDER BY,避免全表掃描
-- 未加 ORDER BY:rows=15,729,009(全表掃描)
-- 加上 ORDER BY id:rows=200(游標讀 200 筆即停止)
SELECT * FROM table1 WHERE status = 1 ORDER BY id LIMIT 200;


避坑指南:
1. Hint 屬於強制干預,升級版本或資料分布變化可能導致反效果,上線必須壓測驗證
2.FORCE INDEX若索引不存在會報錯,USE INDEX較溫和
3. MySQL 8.0 查詢快取已移除,SQL_CACHE/NO_CACHE失效
4.STRAIGHT_JOIN僅影響該 JOIN 順序,不影響子查詢
5. 日常優化首選:加索引、改寫 SQL、調整配置,Hint 為最後手段