背景:一些业务场景需要导出excel的需求,但是面对日益增长的数据,要导出的数据会越来越大。生成表格的时间也会越来越慢。针对这个问题,目前的业务通过两个角度去提速。
1:异步导出
如果数据量达到一定的体量,单单通过同步的话,等待的时间会特别慢。
这个时候,为了照顾用户体验,我们或许可以选择异步来进行导出,就是用户在页面上提交导出申请,然后我们会在队列里面执行生成excel,并且生成之后提醒用户查看。
在这个任务过程中,最好可以分块处理数据,比如:
chunk分块---组块结果集
如果你需要处理成千上百条数据库记录,可以考虑使用 chunk
方法,该方法一次获取结果集的一小块,然后传递每一小块数据到闭包函数进行处理,该方法在编写处理大量数据库记录的 Artisan 命令的时候非常有用。
例如,我们可以将处理全部 users
表数据分割成一次处理 100
条记录的小组块:
DB::table('users')->orderBy('id')->chunk(100, function($users) {
foreach ($users as $user) {
//
}
});
你可以通过从闭包函数中返回 false
来终止组块的运行:
DB::table('users')->orderBy('id')->chunk(100, function($users) {
// 处理结果集...
return false;
});
如果你要在组块结果集中更新数据库记录,组块结果可能会以意想不到的方式被更改。因此,在组块查询中更新记录时,最好使用 chunkById
方法。该方法会自动基于记录的主键对结果集进行分页:
DB::table('users')->where('active', false)
->chunkById(100, function ($users) {
foreach ($users as $user) {
DB::table('users')
->where('id', $user->id)
->update(['active' => true]);
}
});
注:在组块回调中更新或删除记录时,对主键或外键的任何更改都会影响组块查询,甚至会导致相应记录不被包含在组块结果集中。
如果是在chunk里面进行遍历给数组插入数据,必须use引用变量,否则最后的数组并不是全部数据,以我写的例子如下:
2:xlsExcel
不管是laravel-excel或者是\Maatwebsite\Excel ,一旦遇到数据量一大(几万条数据)的话,导出就会变得特别慢,然后我偶然发现xlsExcel的导出效率还是挺高的,实测7w多条数据导出只需要6秒多。所以已经满足我目前业务的需求,贴出laravel下xlsExcel的配置方案:
(1):安装xlsExcel
https://pecl.php.net/package/xlswriterhttps://pecl.php.net/package/xlswriter因为 laravel-xlsExcel扩展要求xlsExcel的版本必须为1.3.7,所以我这次选择下载这个版本
windows:
注意:window 注意版本、是否线程安全、操作系统位数.
因为我电脑的环境,所以我选择php7.4,ts,64位的版本
解压之后放在\php\ext 里面
修改php.ini
extension=xlswriter
重启apache生效。
linux:
wget https://pecl.php.net/get/xlswriter-1.3.2.tgz
tar xf xlswriter-1.3.2.tgz
cd xlswriter-1.3.2
/www/server/php/72/bin/phpize
./configure --with-php-config=/www/server/php/72/bin/php-config --enable-reader
make && make install
echo "extension = xlswriter.so" >> /www/server/php/74/etc/php.ini
也可以自行下载后安装。
(2)安装laravel-xlsExcel扩展
composer require lysice/laravel-xlswriter
将 ServiceProvider
加入到 app.php 中:
'providers' => [
/* * Laravel Framework Service Providers... */
...
\Lysice\XlsWriter\XlsWriterServiceProvider::class
],
发布 Facade
将 Excel
加入到 app.php 中:
'aliases' => [
...
'Excel' => \Lysice\XlsWriter\Facade\Writer::class
],
发布 xlswriter.php
配置文件:
php artisan vendor:publish --provider="Lysice\XlsWriter\XlsWriterServiceProvider"
查看 xlswriter 扩展是否正常安装
php artisan xls:status
//如果成功则显示如下
laravel-xlsWriter info:
+---------+---------------------------------------------+
| version | 1.0 |
| author | lysice<https://github.com/Lysice> |
| docs | https://github.com/Lysice/laravel-xlswriter |
+---------+---------------------------------------------+
XlsWriter extension status:
+-------------------------------+----------------------------+
| loaded | yes |
| xlsWriter author | Jiexing.Wang (wjx@php.net) |
| xlswriter support | enabled |
| Version | 1.3.7 |
| bundled libxlsxwriter version | 1.0.0 |
| bundled libxlsxio version | 0.2.27 |
+-------------------------------+----------------------------+
然后就可以使用了:
调用门面的方法前面需要加斜杠/
处理数据的文件如下:
<?php
namespace App\Exports;
use Lysice\XlsWriter\Interfaces\FromArray;
class StockSummaryDetailXlsExport implements FromArray
{
/**
* @return array */
public function array() : array
{
return [ ['哈哈', 'aaa'],
['哈哈', 'aaa'],
['哈哈', 'aaa'],
['哈哈', 'aaa']
];
}
/**
* @return array
*/
public function headers() : array {
return [];
}
}
目前提速只用到这两种方案,导出大数据的效率提升了80倍。
如果有其他欢迎分享交流。
参考:
1:xlsExcel官方文档
https://xlswriter-docs.viest.me/zh-cn/an-zhuang/ubuntuhttps://xlswriter-docs.viest.me/zh-cn/an-zhuang/ubuntu
2:laravel-xlsExcel官方文档
https://learnku.com/articles/56844https://learnku.com/articles/56844
3: laravel-xlsExcel----git地址
https://github.com/viest/php-ext-xlswriterhttps://github.com/viest/php-ext-xlswriter