MySQL 將資料 (Data)與索引 (Index)分離儲存於不同檔案,這與 Oracle、Sybase 等多數資料庫「索引葉節點直接包含資料」的聚集索引架構截然不同。手冊強調此設計對現代系統更合適,主要優勢在於:
反面:根據索引查找資料需額外一次磁碟 I/O (先讀索引再讀資料),但此成本可透過快取大幅降低。
「盡可能減少磁碟佔用」 是效能調校的基石。較小的表意味著:
| 策略 | 說明 | 效益 |
|---|---|---|
| 選用最小足夠型別 | MEDIUMINT 替代 INT、SMALLINT 替代 MEDIUMINT | 儲存減少 25-50% |
盡量 NOT NULL | 每欄省 1 bit,查詢優化器可簡化判斷邏輯 | 速度提升、空間節省 |
| 固定長度格式 (MyISAM) | 無 VARCHAR/TEXT/BLOB 時自動啟用 | 讀取速度快 (代價:空間略增) |
| 主鍵越短越好 | 主鍵值會重複儲存於所有二級索引 | 所有索引體積縮減 |
| 只建必要索引 | 索引加速讀、拖慢寫 | 寫入效能提升 |
| 前綴索引 | INDEX(name(10)) 僅索引前 10 字元 | 索引檔案大幅縮小 |
| 拆分高頻掃描表 | 熱資料小表 + 冷資料大表 | 掃描熱資料極快 |
col_name(length) 僅索引前綴,大幅縮減索引體積CHAR/VARCHAR/TEXT,不支援前綴,整欄檢索INDEX idx_name (last_name(10), first_name(5))複合索引 INDEX name (last_name, first_name) 可服務:
| 查詢條件 | 是否用到索引 | 說明 |
|---|---|---|
WHERE last_name='Widenius' | ✅ 是 | 左前綴第 1 欄 |
WHERE last_name='W' AND first_name='M' | ✅ 是 | 左前綴第 1+2 欄 |
WHERE last_name='W' AND (first_name='M' OR first_name='N') | ✅ 是 | 左前綴 + IN/OR |
WHERE last_name='W' AND first_name >= 'M' AND first_name < 'N' | ✅ 是 | 左前綴 + 範圍 |
WHERE first_name='Michael' | ❌ 否 | 非左前綴 (跳過第 1 欄) |
WHERE last_name='W' OR first_name='M' | ❌ 否 | OR 打破左前綴連續性 |
WHERE a=1 AND b>2 AND c=3 中 c 無法利用索引SELECT a,b FROM t WHERE a=1),避免回表,極大提升效能| 引擎 | 索引/資料分離 | 鎖粒度 | 事務 | 適用場景 |
|---|---|---|---|---|
| MyISAM | 是 | 表鎖 | 否 | 讀多寫少、全文搜尋、唯讀分析 |
| InnoDB | 否 (聚集索引) | 行鎖 | 是 | OLTP、高併發寫入、需 ACID |
| MEMORY | 記憶體內 | 表鎖 | 否 | 暫存表、快取、極速查找 |
| BDB | 否 | 頁鎖 | 是 | 舊版替代方案,已棄用 |
手冊建議:根據應用存取模式選擇引擎,同一資料庫可混用多引擎。
NOT NULL 為預設ANALYZE TABLE 更新統計資料庫結構優化是一次性投入、長期受益的高報酬工作,值得在設計階段深思熟慮。