innodb_buffer_pool_size (記憶體 60-70%)、innodb_log_file_size (1-4GB)、innodb_flush_log_at_trx_commit=1、sync_binlog=1、max_connections、thread_cache_size。tags VARCHAR(255) 'tag1,tag2,tag3'、phones JSON (8.0 JSON 類型雖支援但查詢效率低)。article_tags(article_id, tag_id)、user_phones(user_id, phone)。PRIMARY KEY (student_id, course_id))。student_name 僅依賴 student_id (部分依賴) → 冗餘、更新異常。students(student_id, name)、courses(course_id, name)、scores(student_id, course_id, score)。students(sno, name, dept_name, dept_addr) → dept_addr 依賴 dept_name 再依賴 sno (傳遞依賴)。departments(dept_id, name, addr)、students(sno, name, dept_id)。student_course(sno, id_card, course),(sno, id_card) 為候選鍵,但 sno→id_card、id_card→sno,任一單列即可唯一標識 → 違反 BCNF。students(sno, id_card)、student_course(sno, course)。| 場景 | 手法 | 風險控制 |
|---|---|---|
| 高頻 JOIN 查詢 (如訂單+用戶) | 冗餘 user_name 至 orders 表 | 觸發器/應用層雙寫同步;接受極短暫不一致 |
| 聚合統計 (如用戶訂單數、總金額) | 冗餘計數欄位 order_count, total_amount | 定時任務重算校驗;或用 Redis 緩存 |
| 多層級分類展示 | Closure Table / 物化路徑 path: 1/5/12/ | 移動節點時批次更新路徑 |
| 大文本/Blob | 拆至獨立表 order_details(order_id, content) | 主表輕量,覆蓋索引命中率高 |
-- 整數:按範圍選最小
TINYINT UNSIGNED (0-255) -- 狀態、類型、性別
SMALLINT UNSIGNED (0-65535) -- 郵編、小範圍計數
MEDIUMINT UNSIGNED (0-16M) -- 中等計數
INT UNSIGNED (0-4B) -- 通用 ID、外鍵
BIGINT UNSIGNED (0-18EB) -- 訂單號、流水號、主鍵
-- 定點數:金額、精度敏感
DECIMAL(10,2) -- 99,999,999.99
DECIMAL(12,4) -- 匯率、單價
-- 字串:定長 vs 變長
CHAR(32) -- MD5、UUID、固定編碼
VARCHAR(255) -- 通用短文本
TEXT/MEDIUMTEXT/LONGTEXT -- 長文本 (離頁存儲,慎用)
-- 時間:統一 DATETIME(3) 或 TIMESTAMP(3)
DATETIME(3) -- 8 字節,範圍 1000-9999,不受時區影響
TIMESTAMP(3) -- 4 字節,1970-2038,自動時區轉換
(a,b,c) 支援 a/a,b/a,b,c 查詢。COUNT(DISTINCT col)/COUNT(*) > 0.8 適合建索引;性別、狀態低選擇性不建單列索引。SELECT a,b FROM t WHERE c=1 → 索引 (c,a,b) 避免回表。KEY(a) + KEY(a,b) → 刪除前者。KEY(fk_id)。user_id (用戶維度)、order_id (訂單維度)、DATE(created_at) (時間維度)。優化是系統工程,**建模是基石**。堅持「先 3NF 後反範式、代理鍵主鍵、欄位類型最小化、索引服務查詢」四大原則,配合硬體資源合理配置,再針對慢 SQL 精準施策,才能構建高效穩定的 MySQL 系統。下一章將深入索引內部原理與進階優化技巧。