萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 批量更新高效寫法:CASE WHEN、REPLACE INTO、臨時表三大方案效能實測

大量資料需更新不同值時,逐條 UPDATE 效能極差。本文對比三種批量更新方案,附實測數據助你選型。

場景:依 ID 更新不同值

-- 目標:id=1→val=3, id=2→val=4, id=3→val=5

方案一:CASE WHEN 單語句更新(推薦中小量)

UPDATE `categories`
SET `display_order` = CASE `id`
    WHEN 1 THEN 3
    WHEN 2 THEN 4
    WHEN 3 THEN 5
  END
WHERE `id` IN (1,2,3);
  • 單次 SQL 完成,減少網路往返
  • WHERE IN 縮小掃描範圍,提升效率
  • 多欄位同理擴展

方案二:REPLACE INTO / INSERT ... ON DUPLICATE KEY UPDATE

-- REPLACE INTO(本質:DELETE + INSERT,缺失欄位會重置為預設值)
REPLACE INTO `test_tbl` (`id`, `dr`) VALUES (1,'2'), (2,'3'), (3,'4');

-- INSERT ... ON DUPLICATE KEY UPDATE(僅更新指定欄位,保留其他)
INSERT INTO `test_tbl` (`id`, `dr`) VALUES (1,'2'), (2,'3'), (3,'4')
ON DUPLICATE KEY UPDATE `dr` = VALUES(`dr`);
  • 需表有 PRIMARY KEY 或 UNIQUE KEY
  • REPLACE 會觸發 DELETE 觸發器,INSERT ... ON DUPLICATE KEY 不會

方案三:臨時表 + JOIN 更新(超大量最快)

CREATE TEMPORARY TABLE `tmp_update` (
  `id` INT PRIMARY KEY,
  `dr` VARCHAR(50)
);
INSERT INTO `tmp_update` VALUES (1,'gone'), (2,'xx'), (100000,'yy');

UPDATE `test_tbl` t
JOIN `tmp_update` tmp ON t.`id` = tmp.`id`
SET t.`dr` = tmp.`dr`;
  • 需 CREATE TEMPORARY TABLES 權限
  • 批次寫入臨時表,再單次 JOIN 更新,鎖表時間最短

效能實測(10 萬筆更新)

方案Real TimeUser CPUSys CPU
逐條 UPDATE15.56s1.68s1.37s
REPLACE INTO1.39s0.06s0.01s
INSERT ... ON DUPLICATE KEY1.47s0.05s0.01s
臨時表 + JOIN0.64s0.06s0.00s

選型建議

資料量推薦方案理由
< 1,000 筆CASE WHEN語法簡單、無額外物件、易維護
1,000 ~ 100,000 筆INSERT ... ON DUPLICATE KEY UPDATE不重置其他欄位、效能優異、標準 SQL
> 100,000 筆臨時表 + JOIN批次寫入、鎖定時間最短、可控制交易大小

PHP 產生 CASE WHEN SQL 範例

$display_order = [1=>4, 2=>1, 3=>2, 4=>3, 5=>9];
$ids = implode(',', array_keys($display_order));
$sql = "UPDATE `categories` SET `display_order` = CASE `id` ";
foreach ($display_order as $id => $ordinal) {
    $sql .= sprintf("WHEN %d THEN %d ", $id, $ordinal);
}
$sql .= "END WHERE `id` IN ($ids)";

根據資料量與業務限制選擇適合方案,能讓批量更新從「分鐘級」降為「秒級」。

copyright © 萬盛學電腦網 all rights reserved