查詢是資料庫最常用的操作,雖然流程簡單(客戶端送 SQL → 伺服器執行 → 回傳結果),但不同寫法與設定對效能影響巨大。本文深入探討六大優化方向。
MySQL 4.0.1+ 內建查詢快取。啟用方式:在 my.ini 設定 query_cache_type=1。啟用後,相同的 SELECT 會直接從快取回傳結果。
注意事項:
SELECT * FROM t 與 select * from t 視為不同查詢SQL_NO_CACHE 強制略過快取:SELECT SQL_NO_CACHE col1, col2 FROM t;query_cache_type=2(DEMAND 模式),僅對加上 SQL_CACHE 的查詢啟用快取當 WHERE 條件符合的資料佔全表比例過高(約 30% 以上),MySQL 會自動放棄索引改用全表掃描,因為索引排序成本過高。此閾值因儲存引擎而異。
-- 範例:若 ID=1000 的資料佔 50%,使用 SALE_DATE 索引反而變慢
SELECT AVG(price) FROM sales
WHERE id = 1000 AND sale_date BETWEEN '2004-01-01' AND '2005-12-31';
MySQL 查詢最多只能用一個索引。若 WHERE 已用掉索引,ORDER BY 就無法用索引排序。
-- 原本:WHERE 用 name 索引,ORDER BY sale_date 無索引
SELECT * FROM sales WHERE name = 'xxx' ORDER BY sale_date DESC;
-- 解法:建立複合索引 (name, sale_date)
ALTER TABLE sales DROP INDEX name, ADD INDEX (name, sale_date);
限制: WHERE 子句不可包含排序欄位(如 sale_date),否則查詢又會變慢。
條件恆為假的查詢(如 value < 100 AND value > 200 或 name='a' AND name='b'),MySQL 會在執行前分析並直接略過,不掃描資料表。可用 EXPLAIN 驗證:table 欄位為空即表示未實際存取。
| 選項 | 用途 | 範例 |
|---|---|---|
STRAIGHT_JOIN | 強制連接順序 | SELECT ... FROM t1 STRAIGHT_JOIN t2 WHERE ... |
USE INDEX | 限制只考慮指定索引 | SELECT * FROM t USE INDEX (col1, col2) ... |
IGNORE INDEX | 排除特定索引 | SELECT * FROM t IGNORE INDEX (col1) ... |
FORCE INDEX | 強制使用某索引 | SELECT * FROM t FORCE INDEX (col1) ... |
SQL_BUFFER_RESULT | 結果存入暫存表,快速釋放表鎖 | SELECT SQL_BUFFER_RESULT * FROM t ... |
SQL_BIG_RESULT | 分組/去重時建議用暫存表排序 | SELECT SQL_BIG_RESULT col1, COUNT(*) FROM t GROUP BY col1 |
資料庫優化遵循「二八原則」:20% 的 SQL 消耗 80% 的時間。核心在於減少磁碟 I/O、善用循序讀取。持續分析慢查詢、調整索引、善用快取,才能穩定提升效能。