Экспорт огромных данных в xlsx

Мне нужно экспортировать огромный набор данных из таблицы базы данных MySQL с движком MYISAM в .xlsx файл в Laravel.

Я использую http://www.maatwebsite.nl/laravel-excel/docs/export, который основан на PHPExcel.

База данных содержит около 500 000 строк с 93 столбцами (около 46 500 000 ячеек) и довольно много вычислений, касающихся структуры заголовка.

Это код, который я сейчас использую:

// $excel_data contains some data regarding the project, nothing relevant here
$output = Excel::create('myproject-' . $excel_data->project->name . '-'.date('Y-m-d H:i:s') . '-export', function($excel) use($excel_data) {

        // Set the title
        $excel->setTitle($excel_data->project->name . ' Export');

        $excel->sheet('Data', function($sheet) use($excel_data) {

            $rowPointer = 1;

            $query = DB::table('task_metas')
                ->where([
                    ['project_id', '=', $excel_data->project->id],
                    ['deleted_at', '=', null]
                ])
                ->orderBy('id');

            $totalRecords = $query->count();
            // my server can't handle a request that returns more than 20k rows so I am chunking the results in batches of 15000 to be on the safe side
            $query->chunk(15000, function($taskmetas) use($sheet, &$rowPointer, $totalRecords) {
                // Iterate over taskmetas
                foreach ($taskmetas as $taskmeta) {
                    // other columns and header structure omitted for clarity
                    $sheet->setCellValue('A' . $rowPointer, $rowPointer);
                    $sheet->setCellValue('B' . $rowPointer, $taskmeta->id);
                    $sheet->setCellValue('C' . $rowPointer, $taskmeta->url);

                    // Move on to the next row
                    $rowPointer++;
                }
                // logging the progress of the export
                activity()
                    ->log("wrote taskmeta to row " . $rowPointer . "/" . $totalRecords);

                unset($taskmetas);
            });
        });

    });

    $output->download('xlsx');

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

Экспорт в CSV работает отлично, примерно через 10 минут он компилирует файл и загружает его, однако я не могу с этим работать - выходной файл должен быть xlsx,

Что я могу сделать, чтобы ускорить процесс создания файла? Я также открыт для других альтернатив, пока я могу достичь тех же результатов.

1 ответ

Решение

У меня есть 3 предложения:

  1. Используя курсор (хотя до сегодняшнего дня я не выяснил, лучше ли он, чем кусок - возможно, ваш случай мог бы это проверить) - С уважением, я использовал только этот и его с Eloquent.

  2. уменьшить размер куска. Я думаю, что загрузка 15000 записей в память уже является проблемой.

  3. Сначала создайте файл Excel, а затем используйте rows() метод на листе, чтобы добавить несколько строк. (это может не сработать, так как требует массив)

Другие вопросы по тегам