PDO批量插入10万行怎么做?单条execute和多值INSERT差多少倍?
使用pdo进行批量插入时,核心策略是构建包含多个占位符的长sql语句并一次性执行。对于10万行数据,直接循环调用`$stmt->execute()`会导致极高的网络往返开销和事务日志压力,性能极差;而将数据拼接成多值insert(例如每批500-1000行)可以显著减少数据库交互次数,通常比单条执行快几十到上百倍。具体做法是将数据分组,生成形如`insert into table (col) values (...), (...)`的语句,并通过预处理或安全拼接后执行。

如何配置PDO以支持高效的大批量插入?
要实现高效的批量插入,必须正确配置PDO的属性,特别是关闭自动提交(`AUTOCOMMIT`)并手动管理事务。默认情况下,每条SQL语句都会隐式提交,这会导致严重的I/O瓶颈。通过设置`PDO::ATTR_AUTOCOMMIT => false`,可以将所有插入操作包裹在一个显式事务中,仅在最后调用`commit()`,从而极大提升写入速度。此外,应使用预处理语句(`prepare`)来避免重复解析SQL,并确保在循环外绑定参数或一次性传入数组。

$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
$sql = "INSERT INTO users (name, email) VALUES (:name, :email)";
$stmt = $pdo->prepare($sql);
$batchSize = 1000;
$data = generateData(100000); // 假设生成10万行数据
try {
foreach (array_chunk($data, $batchSize) as $chunk) {
foreach ($chunk as $row) {
$stmt->execute([':name' => $row['name'], ':email' => $row['email']]);
}
}
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}多值INSERT与预处理循环的性能差异有多大?
多值INSERT(Multi-Row INSERT)是指在一个`INSERT`语句中包含多个`VALUES`子句,例如`INSERT INTO t (c) VALUES (v1), (v2), (v3)`。相比在循环中多次调用`$stmt->execute()`,多值INSERT能进一步减少PHP端的数据序列化和网络传输开销。当批次大小设置为500-1000行时,多值INSERT的执行时间通常是单条execute模式的1/10到1/50,具体取决于网络延迟和数据大小。关键在于平衡批次大小:过大可能导致SQL语句过长被截断或内存溢出,过小则无法发挥批量优势。

$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->beginTransaction();
$batchSize = 500;
$data = generateData(100000);
for ($i = 0; $i < count($data); $i += $batchSize) {
$chunk = array_slice($data, $i, $batchSize);
$placeholders = [];
$params = [];
foreach ($chunk as $row) {
$placeholders[] = '(?, ?)';
$params[] = $row['name'];
$params[] = $row['email'];
}
$sql = "INSERT INTO users (name, email) VALUES " . implode(', ', $placeholders);
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
}
$pdo->commit();

















