PHP MySQL批量由BATCH插入准备好的语句

时间:2017-05-01 15:47:14

标签: php mysql prepared-statement bulkinsert

我有一个插入大量数据的脚本。此数据主要是前一个插入的复制,但至少有一个值不同。因此,我准备语句并绑定参数以执行和重复。

但是,我尝试将其写入准备好的批量插入内容,一次插入1000行顶部。不幸的是,我无法让它发挥作用。我现在使用的代码只是一次插入整个数据。但是,这不是必需的,因为数据量可能比测试时大很多。

我现在使用的代码(批量插入一次):

$Data = array(
    array("1", "2", "3", "4"),
    array("1", "2", "3", "5"),
    array("1", "2", "3", "6"),
    array("1", "2", "3", "7"),
    array("1", "2", "3", "8"),
    //ETC
    );
//AS YOU CAN SEE, ONLY COL4 CHANGES
$sql = $mysqli->prepare("INSERT INTO `Table` (Col1, Col2, Col3, Col4) VALUES ".implode(', ', array_fill(0, count($Data), "(?, ?, ?, ?)")));
foreach ($Data as $InsertData) {
    $sql->bind_param('iiii', $InsertData[0], $InsertData[1], $InsertData[2], $InsertData[3]);
    }
$sql->execute();

我想要实现的是,数据将使用如上所述的预准备语句插入,但每批限制为1000(或任何其他数字)。我无法让这个工作。我尝试使用array_splice和其他方法,但我无法使用它。

2 个答案:

答案 0 :(得分:1)

您可以使用简单的for循环来分段工作,而不是尝试添加更多的数组副本:

$arraySize = count($Data);
for ( $i = 0; $i < $arraySize; $i+=1000 )    {
  // Number of elements in this chunk
  $thisChunk = min(1000, $arraySize-$i);
  // Prepare your statement
  $sql = $mysqli->prepare("INSERT INTO `Table` (Col1, Col2, Col3, Col4) VALUES ".implode(', ', array_fill(0, $thisChunk, "(?, ?, ?, ?)")));
  for( $j = $i; $i < $i + $thisChunk; $j++ )  {
    // Bind this data from $Data[$j]
  }
}

这当然会每次重新准备你的陈述,如果你知道thisChunk是1000个元素,你可以避免这个。

答案 1 :(得分:0)

您应该考虑使用LOAD DATA INFILE。

与使用批量行的INSERT相比,它可能要快得多,即使您必须先写出临时文件。

$Data = array(
    array("1", "2", "3", "4"),
    array("1", "2", "3", "5"),
    array("1", "2", "3", "6"),
    array("1", "2", "3", "7"),
    array("1", "2", "3", "8"),
    //ETC
    );

$tempname = tempnam("/tmp", "data");
$fp = fopen($tempname, "w");
foreach ($Data as $fields) {
    fputcsv($fp, $fields);
}
fclose($fp);
if ($mysqli->query("
  LOAD DATA INFILE '$tempname' INTO TABLE `Table`
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"'
  ") === false) {
    error_log($mysqli->error);
}
unlink($tempname);

阅读https://dev.mysql.com/doc/refman/5.7/en/load-data.html,确保您了解LOCAL选项以及local_infilesecure_file_priv配置选项。

相关问题