Подтвердить что ты не робот

Обработать очень большой файл csv без тайм-аута и ошибки памяти

В настоящий момент я пишу импорт script для очень большого CSV файла. Проблема заключается в том, что большинство раз она останавливается через некоторое время из-за таймаута или выдает ошибку памяти.

Моя идея теперь должна анализировать CSV файл в шагах "100 строк" ​​и после 100 строк автоматически вызывать script. Я попытался добиться этого с помощью заголовка (location...) и передать текущую строку с помощью get, но это не сработало, как я хочу.

Есть ли лучший способ для этого или кто-то знает, как избавиться от ошибки памяти и таймаута?

4b9b3361

Ответ 1

Я использовал fgetcsv для чтения 120-мегабайтной csv потоковым способом (это правильный английский?). Это читается по строкам, а затем я вставлял каждую строку в базу данных. Таким образом, на каждой итерации сохраняется память в одной строке. script все еще понадобилось 20 мин. бежать. Возможно, я попробую Python в следующий раз... Не пытайтесь загрузить огромный массив csv в массив, который действительно будет потреблять много памяти.

// WDI_GDF_Data.csv (120.4MB) are the World Bank collection of development indicators:
// http://data.worldbank.org/data-catalog/world-development-indicators
if(($handle = fopen('WDI_GDF_Data.csv', 'r')) !== false)
{
    // get the first row, which contains the column-titles (if necessary)
    $header = fgetcsv($handle);

    // loop through the file line-by-line
    while(($data = fgetcsv($handle)) !== false)
    {
        // resort/rewrite data and insert into DB here
        // try to use conditions sparingly here, as those will cause slow-performance

        // I don't know if this is really necessary, but it couldn't harm;
        // see also: http://php.net/manual/en/features.gc.php
        unset($data);
    }
    fclose($handle);
}

Ответ 2

Если вам все равно, сколько времени потребуется и сколько памяти ему нужно, вы можете просто увеличить значения для этого script. Просто добавьте следующие строки в начало script:

ini_set('memory_limit', '512M');
ini_set('max_execution_time', '180');

С помощью функции memory_get_usage() вы можете узнать, сколько памяти вашему script нужно найти для значения memory_limit.

Вы также можете посмотреть fgets(), который позволяет вам читать файл по строкам. Я не уверен, что это занимает меньше памяти, но я действительно думаю, что это сработает. Но даже в этом случае вам нужно увеличить max_execution_time до более высокого значения.

Ответ 3

Я нахожу загрузку файла и вставку с использованием mysql LOAD DATA LOCAL запрос быстрого решения, например:

    $sql = "LOAD DATA LOCAL INFILE '/path/to/file.csv' 
        REPLACE INTO TABLE table_name FIELDS TERMINATED BY ',' 
        ENCLOSED BY '\"' LINES TERMINATED BY '\r\n' IGNORE 1 LINES";
    $result = $mysqli->query($sql);

Ответ 4

О. Просто сделайте этот script вызванным как CLI, а не через глупый веб-интерфейс. Таким образом, на это не повлияет лимит времени выполнения.
И не сохраняйте анализируемые результаты навсегда, но немедленно их записывайте - так что вы также не будете затронуты лимитом памяти.