MySQL 效能優化是系統工程,涵蓋架構、結構、查詢、配置各層面。本文蒐整 8 大高影響力優化原則,附實戰範例與反模式對照。
TINYINT (1B) > SMALLINT (2B) > MEDIUMINT (3B) > INT (4B) > BIGINT (8B)。郵遞區號用 CHAR(6) 而非 VARCHAR(255)。CHAR 適合固定長 (MD5、UUID、國家代碼);VARCHAR 適合變長。CHAR 不需長度前綴,查詢略快但浪費空間。反模式 (子查詢):
SELECT * FROM customerinfo
WHERE CustomerID NOT IN (SELECT CustomerID FROM salesinfo);
優化 (LEFT JOIN + IS NULL):
SELECT c.* FROM customerinfo c
LEFT JOIN salesinfo s ON c.CustomerID = s.CustomerID
WHERE s.CustomerID IS NULL;
原理:JOIN 由優化器直接執行巢狀迴圈/哈希聯接;子查詢 (特別是 NOT IN) 常導致全表掃描或臨時表建立。確保被驅動表聯接欄位有索引。
SELECT Name, Phone FROM client
UNION
SELECT Name, BirthDate FROM author
UNION
SELECT Name, Supplier FROM product;
注意:所有 SELECT 欄位數、順序、類型必須相容。UNION ALL 保留重複、免排序、效能更高 (若業務允許重複)。
START TRANSACTION;
INSERT INTO salesinfo SET CustomerID = 14;
UPDATE inventory SET Quantity = 11 WHERE item = 'book';
COMMIT;
LOCK TABLE inventory WRITE;
SELECT Quantity FROM inventory WHERE item = 'book';
-- 業務邏輯計算
UPDATE inventory SET Quantity = 11 WHERE item = 'book';
UNLOCK TABLES;
適用:MyISAM、批次匯入、唯寫場景。InnoDB 首選行鎖/交易,表鎖會阻塞所有並發。
CREATE TABLE customerinfo (
CustomerID INT NOT NULL PRIMARY KEY
) ENGINE=InnoDB;
CREATE TABLE salesinfo (
SalesID INT NOT NULL,
CustomerID INT NOT NULL,
PRIMARY KEY (CustomerID, SalesID),
FOREIGN KEY (CustomerID) REFERENCES customerinfo(CustomerID) ON DELETE CASCADE
) ENGINE=InnoDB;
關鍵:ON DELETE CASCADE 級聯刪除;ENGINE=InnoDB 必須 (MyISAM 不支援 FK)。外鍵有鎖開銷,高併發寫入可考慮應用層維護。
WHERE、JOIN ON、ORDER BY、GROUP BY 欄位(a,b,c) 支援 a/a,b/a,b,cSELECT a,b FROM t WHERE c=1 → 索引 (c,a,b) 避免回表ANALYZE TABLE 更新統計;OPTIMIZE TABLE 整理碎片 (或 ALTER TABLE ... ENGINE=InnoDB)| 反模式 | 優化寫法 | 原理 |
|---|---|---|
WHERE YEAR(OrderDate) < 2001 | WHERE OrderDate < '2001-01-01' | 函數導致索引失效;常數比較可用索引範圍掃描 |
WHERE Amount/7 < 24 | WHERE Amount < 24*7 | 運算在欄位上阻礙索引;移至常數側 |
WHERE name LIKE 'MySQL%' | WHERE name >= 'MySQL' AND name < 'MySQM' | 前綴 LIKE 可用索引;但範圍查詢更穩定 |
WHERE col IS NULL (索引欄) | WHERE col = '' 或 col = 0 | NULL 不存入 B+ 樹 (單列索引);改用預設值 |
SELECT * | SELECT col1, col2 | 減少網路/IO/緩衝池壓力;利用覆蓋索引 |