将大量数据导出到 xlsx
Export huge data into xlsx
我需要使用 MYISAM 引擎从 MySQL 数据库 table 导出一个巨大的数据集到 Laravel.
中的 .xlsx
文件中
我正在使用 maatwebsite/laravel-excel package, which is based on PHPExcel。
数据集包含大约 500,000 行和 93 列(大约 46,500,000 个单元格),以及关于 header 结构的大量计算。
这是我目前使用的代码:
// $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
.
如何加快文件创建过程?只要我能达到相同的结果,我也愿意接受其他选择。
我有3条建议:
使用 cursor(虽然直到今天,我还没有发现它是否比块更好 - 也许你的情况可以验证这一点) - 真诚地我只使用了这个和它 Eloquent.
减小块的大小。我认为在内存中加载 15000 条记录已经是个问题了。
首先创建 excel 文件,然后在 sheet 上使用 rows()
方法追加多行。 (这可能效果不佳,因为它需要一个数组)
我需要使用 MYISAM 引擎从 MySQL 数据库 table 导出一个巨大的数据集到 Laravel.
中的.xlsx
文件中
我正在使用 maatwebsite/laravel-excel package, which is based on PHPExcel。
数据集包含大约 500,000 行和 93 列(大约 46,500,000 个单元格),以及关于 header 结构的大量计算。
这是我目前使用的代码:
// $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
.
如何加快文件创建过程?只要我能达到相同的结果,我也愿意接受其他选择。
我有3条建议:
使用 cursor(虽然直到今天,我还没有发现它是否比块更好 - 也许你的情况可以验证这一点) - 真诚地我只使用了这个和它 Eloquent.
减小块的大小。我认为在内存中加载 15000 条记录已经是个问题了。
首先创建 excel 文件,然后在 sheet 上使用
rows()
方法追加多行。 (这可能效果不佳,因为它需要一个数组)