資料庫設計是效能的基石。三範式(3NF)確保資料儲存的高效與擴展性,特別是 OLTP 系統必須遵循。然而,嚴格遵循 3NF 常導致查詢需 JOIN 多張表,拖垮效能。此時,「適度反範式化」——即有意引入冗余——能換來查詢速度的飛躍。關鍵在於「適度」與「理由充分」。

某系統為提升學生活動記錄檢索速度,將「單位名稱」冗余至記錄表。單位表僅 500 筆,記錄表卻有 200 萬筆/年。原表僅含三個 INT 與一個 TIMESTAMP(16 字節),加入 VARCHAR(32) 後體積膨脹 3 倍,I/O 成倍增加。更糟的是,更新一個單位名稱需同步修改 4000 條冗余記錄。這類「小表冗大表、高頻更新」的反範式化,絕對得不償失。

「學生考試總分」冗余自「得分情況」彙總。記錄比約 1:100,且判卷分數極少變動。以極小的儲存成本換取彙總查詢的零運算,這才是教科書級的適度反範式化。
查詢主導型應用中,缺失索引等同於全表掃描。大表小結果集時,全掃描將引發災難性效能崩塌。但「性別」這類基數極低的欄位建索引,不僅無益,還拖慢寫入——這就是「過度索引」。
查詢 WHERE area='beijing' AND age=22,單列索引僅能用一個,複合索引 (area, age) 則能一次命中。更妙的是,(area, age, salary) 等價於同時擁有 (area,age,salary)、(area,age)、(area) 三個索引。建立時,將最常用的過濾列放最左,依序遞減。
含 NULL 的列不會被納入索引;複合索引中任一列有 NULL,該列對該索引失效。設計時請給欄位預設值,避免 NULL。
CHAR(255) 列若前 10-20 字符已足夠區分,僅索引前綴。短索引加快查詢、減少磁碟 I/O、節省空間,一舉三得。
MySQL 單次查詢只用一個索引。WHERE 已用索引時,ORDER BY 列無法再用索引。能用預設排序就別排序;多列排序必須建複合索引。
LIKE '%aaa%' 走全掃,LIKE 'aaa%' 才能用索引。非必要不用 LIKE,用必用對。
WHERE YEAR(adddate) < 2007 導致全表掃描。改寫為 WHERE adddate < '2007-01-01',索引秒回。
兩者皆不走索引。NOT IN 改 NOT EXISTS,id <> 3 改 id > 3 OR id < 3。