查詢優化是數據庫應用系統成敗的關鍵。MySQL 雖速度優異,但面對複雜業務仍需系統性調優。本文從索引設計、SQL 改寫技巧、數據加載策略、硬件資源規劃四大維度,給出可落地的優化方法論與避坑原則。
| 引擎 | 數據/索引存儲 | 主鍵特殊性 |
|---|---|---|
| MyISAM | 分離:.MYD 數據,.MYI 索引 | 非聚簇,主鍵同普通索引 |
| BDB | 同一文件 | 聚簇索引 |
| InnoDB | 共享表空間 | **聚簇索引**,二級索引葉子存主鍵值 |
InnoDB 主鍵越短,二級索引越小,緩存命中率越高 → 業務主鍵優先用自增整數/短業務碼。
INT 優於 BIGINT,CHAR(10) 優於 VARCHAR(100),前綴索引 col(10) 替代全長。INDEX (a,b,c) 支援 a、a,b、a,b,c,不支援 b、c、b,c。log_queries_not_using_indexes=ON 會記錄大量全表掃描,需人工篩選真慢查詢。OPTIMIZE TABLE 整理碎片:VARCHAR 更新導致行分裂、碎片化,影響掃描效率。VARBINARY。ALTER TABLE t ADD INDEX idx_crc32 ((CRC32(long_col))),對長文本按哈希值索引。WHERE int_col = '123' 隱式轉換導致索引失效 → WHERE int_col = 123 或 WHERE str_col = '123'。WHERE YEAR(date_col) = 2023 → WHERE date_col >= '2023-01-01' AND date_col < '2024-01-01'。LIKE '%abc%' 無法用索引 → 全文索引/Elasticsearch/應用層倒排。IN vs EXISTS vs JOIN,EXPLAIN 對比 rows/type/Extra。WHERE a=1 OR b=2 往往全表掃描 → SELECT * FROM t WHERE a=1 UNION ALL SELECT * FROM t WHERE b=2 AND a!=1(各走各索引)。LIMIT 1000000, 20 → WHERE id > last_id ORDER BY id LIMIT 20。LOAD DATA INFILE 碾壓 INSERT:單事務、禁用二級索引維護、順序寫入,速度提升 10-20 倍。START TRANSACTION; INSERT ...; INSERT ...; COMMIT; 批量提交。LOCK TABLES t WRITE; INSERT ...; INSERT ...; UNLOCK TABLES; 減少鎖開銷。CREATE TABLE ...; LOAD DATA ...; CREATE INDEX ...; 避免導入過程中反覆維護 B+ 樹。innodb_buffer_pool_size 設物理內存 60-80%,熱數據全內存,I/O 降為 0。innodb_io_capacity 對應調大。innodb_parallel_read_threads),充分利用核心。EXPLAIN、執行時間、掃描行數、返回行數。pt-query-digest 按「總耗時 = 平均耗時 × 執行次數」排序。SHOW GLOBAL STATUS、Performance Schema、Sys Schema 可視化告警。查詢優化無銀彈,有體系:**索引是槓桿、SQL 是手術刀、加載是搬運工、硬件是地基**。按「零成本索引/改寫 → 低成本參數/加載 → 高成本硬件/架構」順序推進,每步有基線、有驗證、有回滾。將優化從「拍腦袋」變為「有數據、有邏輯、有閉環」的工程實踐,才是 DBA 與開發者的核心競爭力。