PHP MySQL Bulk вставляет BATCH с подготовленными операторами

У меня есть скрипт, который вставляет много данных. Эти данные в основном являются копией предыдущей вставки, однако, по крайней мере, одно значение отличается. Поэтому я готовлю заявление и связываю параметры для выполнения и повторения.

Тем не менее, я попытался записать это на подготовленную пакетную вставку, вставляя по 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 и другие методы, но я не мог заставить его работать.

0

Решение

Вместо того, чтобы пытаться добавить больше копий массива, вы можете использовать простые циклы 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

Другие решения

Вы должны рассмотреть возможность использования 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_infile а также secure_file_priv параметры конфигурации.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector