Значит так. Есть метод, который сканит урл некоего сайта, тащит к себе csv файл и постепенно добавляет в базу или обновляет существующие записи из него. Файл большой(порядка 500к записей на ~660мб), поэтому разбито все на небольшие кусочки и вызывается раз в n минут. Суть надеюсь понятна. Подкиньте идей по оптимизации? (особенно интересует внутренний цикл с запросом =))
/**
* Сканирует 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];
}