Экспорт большой таблицы MySQL в CSV laravel / php ~ 300k + строк - PullRequest
0 голосов
/ 13 февраля 2019

Я создаю приложение-запрос для пользователей, чтобы отфильтровать несколько таблиц, а затем загрузить результаты в виде CSV-файлов, сделать это с небольшими возвращаемыми результатами оказалось очень легко, но некоторые из возвращаемых наборов данных будут иметь размер более 300 тыс. И болееданные.

Были выброшены ошибки тайм-аута, поэтому мне нужен новый подход.Приложение написано в Laravel.

Я смог выполнить необработанный запрос и создал csv с 380k строками данных, но --secure-file-priv заставил меня поместить файл в определенное место.Мне нужно, чтобы файл загрузки был доступен пользователю, отфильтровавшему данные.

мой текущий 3 подхода выглядит следующим образом:

//        $performance = DB::select("SELECT * from performance_datas INTO OUTFILE '/var/lib/mysql-files/performance_data2.csv' FIELDS ENCLOSED BY '\"' TERMINATED BY ';' ESCAPED BY '\"' LINES TERMINATED BY '\r\n' ;");

Этот необработанный запрос создал нужный файл, но я не знаю, как сделать его доступным для загрузки пользователем.

Подход № 2:

$headers = array(
        'Content-Type'        => 'text/csv',
        'Cache-Control'       => 'must-revalidate, post-check=0, pre-check=0',
        'Content-Disposition' => 'attachment; filename=performances.csv',
        'Expires'             => '0',
        'Pragma'              => 'public',
    );

    $response = new StreamedResponse(function() use($filename){
        // Open output stream
        $handle = fopen($filename, 'w');

        // Add CSV headers
        fputcsv($handle, [
            "id", "ref", "DataSet", "PubID", "TrialID", "TrtID", "SubjectID", "Site_Sample", "Day_Sample",
            "Time_Sample", "VarName", "VarValue", "VarUnits", "N", "SEM", "SED", "VarType"
        ]);

        PerformanceData::all()
            ->chunk(1500, function($datas) use($handle) {
                foreach ($datas as $data) {
                    // Add a new row with data
                    fputcsv($handle, [
                        // put data in file
                    ]);
                }
            });

        // Close the output stream
        fclose($handle);
    }, 200, $headers);

Время ожидания истекло.Я использовал Laravel для получения :: all () в этом случае, это был бы самый большой набор данных для этой конкретной таблицы.

Подход 3 был просто различными вариантами подхода 2 с теми же результатами тайм-аута.

Мне нужно, чтобы пользователь мог создать CSV-файл и загрузить его после его готовности или создать и загрузить его напрямую.

Открыт для любых предложений!

...