使用 INSERT INTO ... VALUES (...), (...), ... 多值語法,可將 N 次網絡往返合併為 1 次,大幅提升批量寫入吞吐。本文對比循環插入與批量插入的代碼寫法、效能數據、事務特性與最佳實踐。
INSERT INTO `table` (col1, col2, col3)
VALUES
('val1_1', 'val1_2', 'val1_3'),
('val2_1', 'val2_2', 'val2_3'),
...
('valN_1', 'valN_2', 'valN_3');
max_allowed_packet 限制,超大批次需分片$b = 14;
for ($a = 0; $a < 100; $a++) {
$sql = "INSERT INTO roles (uid, rid) VALUES ($a, $b)";
mysql_query($sql); // 100 次網絡往返、解析、執行
}
$b = 14;
$values = [];
for ($a = 0; $a < 100; $a++) {
$values[] = "($a, $b)";
}
$sql = "INSERT INTO roles (uid, rid) VALUES " . implode(',', $values);
mysql_query($sql); // 1 次網絡往返
$pdo->beginTransaction();
$stmt = $pdo->prepare("INSERT INTO roles (uid, rid) VALUES (?, ?)");
for ($a = 0; $a < 100; $a++) {
$stmt->execute([$a, 14]);
}
$pdo->commit(); // 顯式事務,可控回滾
| 方式 | 耗時 | 相對提升 |
|---|---|---|
| 循環插入 (30 次) | ~450 ms | 基準 |
| 批量插入 (1 次) | ~50 ms | 9 倍快 |
數據量越大、網絡延遲越高,優勢越明顯。百萬級導入建議分批 (每批 1000-5000 行) 配合 LOAD DATA INFILE。
| 參數 | 建議值 | 說明 |
|---|---|---|
| max_allowed_packet | 64M - 256M | 單條 SQL 最大長度,批量插入易超限 |
| bulk_insert_buffer_size | 32M - 128M | MyISAM 批量插入緩存,InnoDB 無效 |
| innodb_log_file_size | 128M+ | 大事務產生大量 Redo,需足夠日誌空間 |
| autocommit | OFF (顯式事務) | 批量插入建議關閉自動提交,手動控制事務邊界 |
SET autocommit=0,批次結束 COMMITDROP INDEX,導入後 CREATE INDEXmax_allowed_packet → Packet too large 錯誤INSERT IGNORE 或 ON DUPLICATE KEY UPDATE批量插入是提升寫入吞吐的「銀彈」。掌握多值語法、分批策略、事務邊界與配置調優,讓數據導入從小時級縮短至分鐘級。