Answer the question
In order to leave comments, you need to log in
Throw in an idea for optimizing this miracle?
So so. There is a method that scans the url of a certain site, drags a csv file to itself and gradually adds to the database or updates existing records from it. The file is large (about 500k records per ~660mb), so everything is broken into small pieces and called once every n minutes. I hope the point is clear. Any suggestions for optimization? (particularly interested in the inner loop with the request =))
/**
* Сканирует CSV файл и полученные данные записывает в базу данных.
* Строка в файле: id|title|duration|post_date|link|screenshots_prefix|screenshots|custom1|custom2|custom3
*
* @param int $numFieldParse количество строк, добавляемых\обновляемых за одну транзакцию.
*
* @return array: success - статус завершения, reason - результат выполнения.
*/
public function parseCSV($numFieldParse = 300)
{
if (! $this->init)
return false;
$csv_data = [];
$csvFile = _LOG_DIR_ . "/em_parse.csv";
if ($numFieldParse == 'all') {
$numFieldParse = 9999999;
unlink ($csvFile);
}
$csv_data = file($csvFile);
if (empty($csv_data) || !file_exists($csvFile)) {
$file = $this->params['csv_url'];
// загрузим файл построчно
$csv_data = file($file);
if (false === $csv_data)
return ['success' => false, 'reason' => "CSV файл не доступен для скачивания"];
// если в настройках указано "убрать первую линию, с названиями - убираем ее"
if ($this->params["skip_csv_first_line"] == 1)
array_shift($csv_data);
}
// Вырежем некоторое количество строк для текущей обработки.
if (count($csv_data) > $numFieldParse ) {
$csv = array_splice($csv_data, 0, $numFieldParse);
} else {
$csv = $csv_data;
$csv_data = [];
}
// Затем запишем остатки в файл, из него в будем парсить следующие проходы.
if (false === file_put_contents($csvFile, $csv_data))
return ['success' => false, 'reason' => "Невозможно записать CSV файл в директорию <b>/runtime/embeds</b>"];
$count = 0; // сколько вставилось или обновилось записей.
$chunckedCsv = [];
if (count($csv) >= 100 )
$chunckedCsv = array_chunk($csv, 100);
else
$chunckedCsv[] = $csv;
unset ($csv, $csv_data);
foreach ($chunckedCsv as $csv) {
$this->pdo->beginTransaction();
foreach ($csv as $csvRow) { // парсим строчки файла и нужные переменные записываем в базу.
$item = str_getcsv($csvRow, "|");
$post['embed_id'] = intval(@$item[0]);
$post['title'] = str_replace("'", '"', @$item[1]);
$post['duration'] = @$item[2]; // в секундах
$post['date'] = @$item[3];
$post['source_link'] = @$item[4];
$post['images'] = $this->getScrArray(@$item[5],@$item[6]);
$post['status'] = "0";
$post['video_format'] = $this->videoFormat;
$sql = "INSERT INTO `" . PREFIX . "_embed_manager` (`embed_id`, `title`, `duration`,`date`,`source_link`,`images`,`status`,`video_format`)
VALUES ('{$post['embed_id']}', '{$post['title']}', '{$post['duration']}', '{$post['date']}', '{$post['source_link']}', '{$post['images']}', '{$post['status']}', '{$post['video_format']}')
ON DUPLICATE KEY UPDATE `title`='{$post['title']}', `duration`='{$post['duration']}', `date`='{$post['date']}', `source_link`='{$post['source_link']}', `images`='{$post['images']}', `video_format`='{$post['video_format']}'";
$stmt = $this->pdo->query($sql);
if ($stmt && $stmt->rowCount() > 0) {
$count += $stmt->rowCount();
}
unset($post);
}
$this->pdo->commit();
}
$reason = "Добавлено новых записей: <b>" . $count . "</b>шт.";
return ['success' => true, 'reason' => $reason];
}
Answer the question
In order to leave comments, you need to log in
INSERT INTO ... VALUES('1'),('2'),('3');
much faster than 3 separate inserts.
Separately take and save csv. Then put the queue server and process.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question