對於以數據為核心的應用,數據庫性能直接決定系統吞吐量。優化需遵循「由輕到重、由內到外」原則,依次為:SQL 語句與索引優化、數據庫表結構設計、參數配置調優、硬件資源與架構擴展。前者影響最大,成本最低;後者成本高但效果明顯。
開啟慢查詢日誌是定位性能瓶頸的第一步:
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
記錄執行超過 2 秒的 SQL。日誌文件可能龐大,使用 mysqldumpslow 工具可聚合相似語句(如將 id=1 和 id=2 歸類為 id=N),並支持按查詢時間、行數等排序,快速定位核心問題。
定位慢 SQL 後,用 EXPLAIN 查看執行計劃:
EXPLAIN SELECT * FROM orders WHERE user_id = 100 AND status = 1;
重點關注 type(訪問類型,避免 ALL 全表掃描)、key(實際使用索引)、rows(預估掃描行數)、Extra(Using index、Using where 等提示)。若統計信息過舊,執行 ANALYZE TABLE 更新;必要時用 STRAIGHT_JOIN 強制連接順序。
若查詢字段全部包含在索引中,可實現「索引覆蓋」,避免回表 I/O。例如:
CREATE INDEX idx_user_status_score ON scores(user_id, status, score);
SELECT user_id, score FROM scores WHERE user_id = 100 AND status = 1;
此查詢僅需掃描索引樹即可獲取所有數據。
嚴格遵循第三範式(3NF)利於寫入與擴展,但多表 JOIN 查詢效率低。適度冗余可提升讀性能,但需權衡:
email(20))單表超千萬行時需水平拆分。拆分鍵選擇至關重要:
將大字段(TEXT/BLOB)、低頻字段移出主表:
BIGINT AUTO_INCREMENT(8 字節),避免 UUID(36 字節),JOIN 時差距倍增TIMESTAMP(4 字節,1970-2037)而非 DATETIME(8 字節)TINYINT + 應用層常量,避免 ENUM 擴展困難圖片、文檔只存路徑,數據庫存元數據。避免 BLOB 膨脹導致備份緩慢、緩存池污染。
PowerDesigner 建立關係自動生成外鍵索引,物理模型導出即可,無需手工維護。
考試成績表預插入所有學生記錄(分數為 NULL),查詢時改 LEFT JOIN 為 INNER JOIN,性能提升顯著;同時保留實際參考名單,新生不會誤顯示為「未錄入」。
複雜積分規則(如老師批改作業鏈條積分)改為夜間腳本批量計算:
INSERT INTO teacher_points
SELECT person_id, @semester_id, 301003, 0, @one_marks, assign_date, @one_marks
FROM hom_assignmentinfo ha
JOIN hom_assign_class hac ON ha.assignment_id = hac.assignment_id
WHERE ha.assign_date BETWEEN @time_begin AND @time_end
AND ha.assignment_id NOT IN ( ...複雜子查詢... );
避免實時觸發器對高併發寫入的性能沖擊。
# 元數據內存池
innodb_additional_mem_pool_size = 64M
# 核心緩存池:專用服務器設為物理內存 70-80%
innodb_buffer_pool_size = 5G
# 日誌文件大小:減少檢查點刷盤
innodb_log_file_size = 512M
innodb_log_files_in_group = 2
# 刷盤策略:平衡性能與安全
innodb_flush_log_at_trx_commit = 2
key_buffer_size = 1G # 索引緩存
| 指標 | 異常閾值 | 調優方向 |
|---|---|---|
| Created_tmp_disk_tables | 增長快 | 增大 tmp_table_size |
| Handler_read_rnd_next | 偏高 | 索引失效,檢查 SQL |
| Key_reads / Key_read_requests | > 0.01 | 增大 key_buffer_size |
| Select_full_join | > 0 | 缺少 JOIN 索引 |
| Sort_merge_passes | 偏大 | 增大 sort_buffer_size |
| Threads_created / Connections | > 0.1 | 增大 thread_cache_size |
內存超 4GB 必須用 64 位 OS + 64 位 MySQL,突破 32 位進程 2-3.5GB 限制。
Master 負責寫入,多 Slave 分擔讀請求:
Master (Write)
├─ Slave1 (Read)
├─ Slave2 (Read)
└─ Slave3 (Read)
應用層需區分讀寫連接,或引入中間件(如 MyCat、ProxySQL、Amoeba)實現透明路由,降低開發負擔。