MySQL 5.6.21
CREATE TABLE product (proID INT PRIMARY KEY AUTO_INCREMENT, price DECIMAL(10,2), type INT, dtime DATETIME);
CREATE TABLE producttype (ID INT PRIMARY KEY, amount INT);
INSERT INTO product(price,type,dtime) VALUES(10,0,NOW()),(10,1,NOW()),(10,1,NOW()),(20,2,NOW()),(30,3,NOW());
INSERT INTO producttype(ID) VALUES(1),(2),(3);
UPDATE producttype SET amount = (
SELECT IFNULL(SUM(p.price),0) FROM product p WHERE p.type = producttype.ID GROUP BY p.type
);
-- Rows matched: 4 (含 ID=3,4 無匹配行)
-- 實際更新: 3 行
**缺點**:無匹配行也參與更新,產生額外行鎖、Binlog、Undo。
UPDATE producttype pt
JOIN (
SELECT type, IFNULL(SUM(price),0) AS total FROM product GROUP BY type
) p ON pt.ID = p.type
SET pt.amount = p.total;
-- Rows matched: 3 (僅匹配行)
-- 實際更新: 3 行
**優勢**:只處理有關聯的行,減少鎖競爭與日誌量。
UPDATE t1 SET ... FROM t2 WHERE ... (SQL Server 風格)UPDATE t1 JOIN t2 ON ... SET ... WHERE ...UPDATE 低選擇性表 JOIN 高選擇性表 ... 通常更優| 場景 | 錯誤寫法 | 正確寫法 |
|---|---|---|
| 關聯更新 | UPDATE a,b SET a.c=b.c WHERE a.id=b.id | UPDATE a JOIN b ON a.id=b.id SET a.c=b.c |
| 子查詢聚合回寫 | UPDATE t SET c=(SELECT SUM(x) FROM s WHERE s.id=t.id) | UPDATE t JOIN (SELECT id,SUM(x) s FROM s GROUP BY id) d ON t.id=d.id SET t.c=d.s |
| 大批量更新 | 單條大事務 UPDATE ... WHERE ... | 分批 (LIMIT 1000) + 索引覆蓋 + 監控 Innodb_log_waits |
Handler_read_rnd_next:全表掃描計數,關聯更新應接近 0Innodb_rows_updated:實際更新行數Innodb_row_lock_time_avg:平均鎖等待時間選對更新模式,少鎖、少日誌、快執行。