Сохранить> 10000 записей с помощью saveMany () в CakePHP - PullRequest
0 голосов
/ 04 марта 2012

Я пытаюсь сохранить список из более чем 10000 записей методом CakePHP 2.1, saveMany(). Но это дает мне либо ошибку 500, либо фатальную ошибку «исчерпана память».

Если я отлаживаю весь массив после его обработки (то есть без вызова метода сохранения), время меньше 0,05 с. Но когда я добавляю метод сохранения ($this->saveMany($save, array('validate' => false));), он показывает одну из перечисленных выше ошибок.

Я упоминаю, что я использую InnoDB в качестве механизма хранения в MySQL и PHP в качестве языка сценариев.

Что я делаю не так и как я могу это исправить?

EDIT

Я возвращаюсь к этой проблеме, потому что я «решил», почему это огромное количество записей не сохраняется. Причина в том ... что ни одна запись не сохранена. Я протестировал сохранение только первого элемента в сгенерированном массиве, и вот что это происходит: он увеличивает память до предела, а затем умирает. Я поместил его на свой локальный хост с 2 ГБ памяти, и он все еще дает мне ошибку превышения памяти. Это очень странно, и я не могу понять, почему это происходит. Тот же код, примененный к другой модели, работает как положено. Я воссоздал модель и ее таблицу, но безуспешно. Единственная причина, по которой я могу придумать, - это длина имени таблицы, но для меня это не имеет смысла. Что может генерировать это увеличение памяти только для сохранения одной записи?

1 Ответ

2 голосов
/ 04 марта 2012

Для сохранения 10000 строк может потребоваться некоторое время. Убедитесь, что вы установили ограничение времени php set_time_limit(120); достаточно большой.

Вы также можете попытаться сохранить записи одну за другой, например:

foreach($save as $s){

    $this->create();
    $this->save($s, array('validate' => false));

}

РЕДАКТИРОВАТЬ 1:

Но если исходные данные поступают из базы данных, вы можете скопировать их непосредственно в кеш-таблицу с помощью консоли MySQL или с помощью $this->query();

Или вы можете SELECT это INTO OUTFILE и LOAD DATA INFILE это кеш таблицы.

РЕДАКТИРОВАТЬ 2:

Тогда единственное, что мне приходит в голову, - это сохранить данные в текстовый файл на диске, прочитать их в другой функции и сохранить столько строк, сколько позволяет время / память. Вы также можете попробовать сохранить его в csv-файле и использовать $this->query('LOAD DATA LOCAL INFILE xxx ...');

Мне приходит в голову, что вы должны отключить индексы перед сохранением, чтобы сделать их быстрее. Вы можете сделать это, используя $this->query('ALTER TABLE table DISABLE KEYS;');

...