優化是系統工程,由大到小:架構 → 索引 → SQL → 參數 → 硬體。以下十大技巧覆蓋全鏈路。
EXPLAIN SELECT ... 檢視 type (目標 ≥ ref)、key (實際用索引)、rows (預估掃描行)、Extra (Using filesort/temporary/index)。EXPLAIN ANALYZE 看實際耗時與行數。TINYINT (1B) < SMALLINT (2B) < MEDIUMINT (3B) < INT (4B) < BIGINT (8B)。CHAR,變長用 VARCHAR,避免 TEXT/BLOB 存短字串。TIMESTAMP (4B, 1970-2038) vs DATETIME (8B, 1000-9999) vs INT Unix stamp (4B)。DECIMAL(19,4) 定點數,嚴禁 FLOAT/DOUBLE。INT UNSIGNED 存 INET_ATON() 結果。mysqli::persistent / Java HikariCP / Go db.SetMaxOpenConns 連線池複用。max_connections、wait_timeout、interactive_timeout 配合調整,避免連線洩漏打滿上限。query_cache_type=0 關閉,或 =2 DEMAND + SQL_CACHE 精準控制。-- ❌ 殺索引:函數作用於欄位
WHERE TO_DAYS(NOW()) - TO_DAYS(create_time) <= 7
-- ✅ 索引友善:運算移至常數側
WHERE create_time >= DATE_SUB(NOW(), INTERVAL 7 DAY)
-- 或應用層計算好常數
WHERE create_time >= '2024-01-01 00:00:00'
WHERE varchar_col = 123 → WHERE varchar_col = '123'。LIKE '%abc%' 導致全掃,前綴 LIKE 'abc%' 可用索引。IN (SELECT ...) → EXISTS (SELECT 1 ...) / JOIN。OR 拆分為 UNION ALL (各支路用各自索引)。SELECT * → 明確列出欄位,減少網路/IO/記憶體,利於覆蓋索引。INSERT INTO wordcount (word, cnt) VALUES ('mysql', 1)
ON DUPLICATE KEY UPDATE cnt = cnt + 1;
-- 省去 SELECT 判斷存在性 + INSERT/UPDATE 兩條語句 + 事務開銷
LAST_INSERT_ID(expr) 可獲取自增 ID 或自定義值。slow_query_log=ON, long_query_time=1 (秒), log_queries_not_using_indexes=ON。pt-query-digest (Percona Toolkit) 聚合分析 Top N 慢查詢。| 參數 | 建議值 | 說明 |
|---|---|---|
| innodb_buffer_pool_size | 6G | 佔實體記憶體 70~80% |
| innodb_log_file_size | 1G | 減少檢查點頻率,單檔 ≤ 4G |
| innodb_flush_log_at_trx_commit | 1 | 資料安全;極致效能可設 2 |
| innodb_file_per_table | ON | 獨立表空間,利於回收空間 |
| max_connections | 2000 | 配合連線池上限 |
| table_open_cache | 4000 | 避免頻繁開關表 |
| thread_cache_size | 100 | 減少執行緒建立銷毀 |
| sort_buffer_size / join_buffer_size | 4M / 4M | 每連線分配,勿設過大 |