MySQL 優化是一個系統工程,涵蓋表設計、SQL 語句、索引策略、參數配置、硬體資源、架構拆分等多個維度。本文將零散優化知識點整理為結構化體系,並針對每個維度給出具體可執行的最佳實踐與避坑指南。
| 範式 | 核心規則 | 應用場景 | 權衡 |
|---|---|---|---|
| 第一範式 (1NF) | 屬性原子性,不可再分 | 所有關係型資料庫基礎要求 | 無爭議 |
| 第二範式 (2NF) | 消除部分依賴(非主鍵列完全依賴主鍵) | 複合主鍵表拆分 | 減少冗余,增加 JOIN |
| 第三範式 (3NF) | 消除傳遞依賴(非主鍵列不依賴其他非主鍵列) | 查詢表拆分(如:學號→系別→系辦電話) | 極致規範,查詢需多表關聯 |
逆範式策略(針對讀多寫少場景):
-- 查看慢查詢閾值(預設 10 秒,建議改 1 秒)
SHOW VARIABLES LIKE 'long_query_time';
SET GLOBAL long_query_time = 1;
-- 啟用慢查詢日誌(配置檔永久生效)
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1 -- 記錄未用索引查詢
-- 主鍵索引
ALTER TABLE tb ADD PRIMARY KEY (id);
-- 唯一索引
CREATE UNIQUE INDEX uk_email ON tb(email);
ALTER TABLE tb ADD UNIQUE uk_email (email);
-- 普通索引
CREATE INDEX idx_name ON tb(name);
ALTER TABLE tb ADD INDEX idx_name (name);
-- 組合索引(最左前綴原則)
CREATE INDEX idx_name_age_city ON tb(name, age, city);
-- 全文索引(MyISAM/InnoDB 5.6+)
CREATE FULLTEXT INDEX ft_content ON tb(content);
| 欄位 | 關鍵值 | 含義 | 優化方向 |
|---|---|---|---|
| type | system > const > eq_ref > ref > range > index > ALL | 訪問類型,從優到劣 | 避免 ALL(全表掃描),至少達到 range/ref |
| possible_keys | 可能用到的索引 | 優化器候選索引 | 無則需建立索引 |
| key | 實際使用的索引 | 最終選擇 | 與 possible_keys 差異大需分析 |
| key_len | 索引長度 | 判斷組合索引用了幾列 | 配合字段長度計算 |
| rows | 預估掃描行數 | 越小越好 | 統計資訊不準時會偏差 |
| Extra | Using index / Using where / Using temporary / Using filesort | 額外資訊 | 避免 temporary/filesort |
LIKE '%abc' 不用索引,LIKE 'abc%' 可用WHERE b=1 或 WHERE c=1 不用索引WHERE varchar_col = 123(數字比較字串)導致索引失效WHERE YEAR(date_col) = 2023、WHERE id + 1 = 10WHERE idx_col = 1 OR non_idx_col = 2ALTER TABLE DISABLE/ENABLE KEYS;InnoDB SET unique_checks=0; SET autocommit=0; 批次提交ORDER BY NULL 禁用預設排序| 維度 | MyISAM | InnoDB |
|---|---|---|
| 事務支援 | 不支援 | 支援 (ACID) |
| 鎖粒度 | 表級鎖 | 行級鎖 |
| 全文索引 | 5.6 前支援 | 5.6+ 支援 |
| 崩潰恢復 | 無 | Redo/Undo Log 保證 |
| 並發效能 | 讀多寫少優 | 高並發讀寫優 |
| 外鍵 | 不支援 | 支援 |
| 適用場景 | 唯讀/日誌/非核心表 | 核心業務/高並發/需事務 |
現代最佳實踐: 預設使用 InnoDB,MySQL 5.7+ 已將 InnoDB 設為預設引擎。
[mysqld]
# InnoDB 核心緩衝池(物理內存 60%-80%)
innodb_buffer_pool_size = 4G
innodb_buffer_pool_instances = 4
# Redo Log 容量(減少 checkpoint 衝刷)
innodb_log_file_size = 512M
innodb_log_files_in_group = 2
# 刷盤策略(1 最安全,2 效能優先)
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
# 連接與線程
max_connections = 2000
thread_cache_size = 100
# 查詢快取(5.7 廢用,8.0 移除,慎用)
query_cache_type = 0
query_cache_size = 0
# 臨時表與排序
tmp_table_size = 64M
max_heap_table_size = 64M
sort_buffer_size = 2M
join_buffer_size = 2M
noatime,nodiratimenumactl --interleave=all mysqld| 策略 | 核心思想 | 適用場景 | 工具/中間件 |
|---|---|---|---|
| 垂直拆表 | 大表拆小表(熱/冷欄位分離) | 含 TEXT/BLOB、部分欄位高頻訪問 | 應用層路由 |
| 水平分表 | 同結構表按鍵值分散(取模/範圍/Hash) | 單表 > 2000 萬行、寫入瓶頸 | ShardingSphere, Vitess, TDDL |
| 主從複制 | 主寫從讀,Binlog 異步同步 | 讀壓力大、備份需求 | 原生 GTID、MHA、Orchestrator |
| 讀寫分離 | 中間件路由 SELECT 到從庫 | 讀寫比 > 3:1 | ProxySQL, MyCat, Atlas |
| 分庫分表 | 結合水平分表 + 多實例分散 | TB 級資料、極高並發 | 自研/開源中間件 |
MySQL 優化無銀彈,只有在具體業務場景下,通過持續觀測、假設驗證、迭代調整,才能找到最適配的配置與架構。建議建立團隊優化知識庫,沉澱典型案例與最佳實踐。