У меня есть несколько тысяч записей (хранящихся в таблице в таблице MYSQL), которые мне нужны для «пакетного процесса». Все записи содержат большой JSON. В некоторых случаях JSON составляет более 1 МБ (да, моя БД намного превышает 1 ГБ).Выполнение интенсивного пакетного процесса в PHP и предотвращение исчерпания памяти
У меня есть функция, которая захватывает запись, декодирует JSON, изменяет некоторые данные, перекодирует массив PHP обратно в JSON и сохраняет его обратно в db. Довольно просто. FWIW, это в контексте приложения CakePHP.
Учитывая массив идентификаторов, я пытаюсь сделать что-то вроде этого (очень простой макет кода):
foreach ($ids as $id) {
$this->Model->id = $id;
$data = $this->Model->read();
$newData = processData($data);
$this->Model->save($newData);
}
Вопрос заключается в том, что очень быстро, PHP работает из памяти. При запуске foreach, как это, это почти так, как если бы PHP перемещался из одной записи в другую, не освобождая память, необходимую для предыдущих операций.
Нужно ли все-таки запустить цикл таким образом, чтобы память освобождалась, прежде чем перейти к следующей итерации цикла, чтобы я мог обработать огромное количество данных?
Редактировать: добавление большего количества кода. Эта функция принимает мой JSON, преобразует его в массив PHP, выполняет некоторые манипуляции (а именно, реконфигурирует данные на основе того, что присутствует в другом массиве) и заменяет значения в исходном массиве. JSON - это много слоев, поэтому очень длинные петли foreach.
function processData($theData) {
$toConvert = json_decode($theData['Program']['data'], $assoc = true);
foreach($toConvert['cycles'] as $cycle => $val) {
foreach($toConvert['cycles'][$cycle]['days'] as $day => $val) {
foreach($toConvert['cycles'][$cycle]['days'][$day]['sections'] as $section => $val) {
foreach($toConvert['cycles'][$cycle]['days'][$day]['sections'] as $section => $val) {
foreach($toConvert['cycles'][$cycle]['days'][$day]['sections'][$section]['exercises'] as $exercise => $val) {
if (isset($toConvert['cycles'][$cycle]['days'][$day]['sections'][$section]['exercises'][$exercise]['selectedFolder'])) {
$folderName = $toConvert['cycles'][$cycle]['days'][$day]['sections'][$section]['exercises'][$exercise]['selectedFolder']['folderName'];
if (isset($newFolderList['Folders'][$folderName])) {
$toConvert['cycles'][$cycle]['days'][$day]['sections'][$section]['exercises'][$exercise]['selectedFolder'] = $newFolderList['Folders'][$folderName]['id'];
}
}
if (isset($toConvert['cycles'][$cycle]['days'][$day]['sections'][$section]['exercises'][$exercise]['selectedFile'])) {
$fileName = basename($toConvert['cycles'][$cycle]['days'][$day]['sections'][$section]['exercises'][$exercise]['selectedFile']['fileURL']);
if (isset($newFolderList['Exercises'][$fileName])) {
$toConvert['cycles'][$cycle]['days'][$day]['sections'][$section]['exercises'][$exercise]['selectedFile'] = $newFolderList['Exercises'][$fileName]['id'];
}
}
}
}
}
}
}
return $toConvert;
}
Модель-> прочитать() в основном только говорит торт, чтобы вытащить запись из БД и возвращает его в массив. Есть много вещей, которые происходят за кулисами, кто-то более осведомленный должен был бы объяснить это.
Вы могли бы спать в конце каждого цикла, и если вы используете PHP 5.3 или выше, вы можете (попытаться) вызвать сборщик мусора. –
Как спать поможет? –
@therefromhere дать gc больше времени, чтобы ударить или закончить то, что он делает. –