Laravel Excel import 100.000 record mất bao lâu?
Trên các group trên mạng, mình thấy các bạn hay than thở là có cách nào import nhanh không chứ sao mới có vài nghìn record mà đã mất rất nhiều thời gian rồi!! Nên hôm nay rảnh rổi mình quyết định thử xem là mất bao lâu. Chuẩn bị File excel 1 trăm ngàn record (tải về - mình có đính kèm trong ...
Trên các group trên mạng, mình thấy các bạn hay than thở là có cách nào import nhanh không chứ sao mới có vài nghìn record mà đã mất rất nhiều thời gian rồi!! Nên hôm nay rảnh rổi mình quyết định thử xem là mất bao lâu.
Chuẩn bị
File excel 1 trăm ngàn record (tải về - mình có đính kèm trong source code) nặng 12 MB, có 14 cột
Bắt đầu thôi.
Bước 1: Tạo project laravel mới
composer create-project --prefer-dist laravel/laravel excel-import-100000-record-sample
Bước 2: Tạo database
Tạo database có tên là: excel-import-100000-record sau đó config trong file .env
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=excel-import-1million-record DB_USERNAME=root DB_PASSWORD=
Bước 3: Tạo bảng imports bằng migration
Mình sẽ tạo 1 bảng có tên là: imports có chưa 14 cột tương ứng với 14 cột trong file excel ở trên kia.
php artisan make:migration create_imports_table --create=imports
File xxxx_xx_xx_xxxxxx_create_imports_table.php sẽ sinh tự động, mình sẽ chỉnh sửa một chút như sau:
<?php use IlluminateSupportFacadesSchema; use IlluminateDatabaseSchemaBlueprint; use IlluminateDatabaseMigrationsMigration; class CreateImportsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('imports', function (Blueprint $table) { $table->increments('id'); $table->string('col1'); $table->string('col2'); $table->string('col3'); $table->string('col4'); $table->string('col5'); $table->string('col6'); $table->string('col7'); $table->string('col8'); $table->string('col9'); $table->string('col10'); $table->string('col11'); $table->string('col12'); $table->string('col13'); $table->string('col14'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('imports'); } }
Trong file laravelcmsappProvidersAppServiceProvider.php function boot() thêm dòng này để chạy migrate khỏi bị lỗi.
public function boot() { Schema::defaultStringLength(191); }
Chạy migrate
php artisan migrate
Bước 4: Cài thư viện Excel
Mình sẽ cài thư viện Laravel-Excel bằng cách chạy artisan command
composer require maatwebsite/excel
Bước 5: Đọc file excel và lưu vào database
Vì khi chạy không thông qua giao diện nên mình sẽ tạo 1 command excel:import như sau:
php artisan make:command ImportExcel --command=excel:import
Sau khi file appConsoleCommandsImportExcel.php được tự động sinh ra, mình sẽ viết logic cho nó như sau
<?php namespace AppConsoleCommands; use IlluminateConsoleCommand; class ImportExcel extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'excel:import'; /** * The console command description. * * @var string */ protected $description = 'Command description'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { ini_set('memory_limit', '-1'); set_time_limit(300); // Thời gian bắt đầu $this->showTime(); // Đọc file excel $inputFileName = public_path($path = '100000 Sales Records.csv'); $reader = new PhpOfficePhpSpreadsheetReaderCsv(); $reader->setSheetIndex(0); $spreadsheet = $reader->load($inputFileName); // Load xong file $this->showTime(); // Nạp rows $rows = $spreadsheet->getSheet(0)->toArray(null, true, true, true); $this->showTime(); $arrKeys = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6', 'col7', 'col8', 'col9', 'col10', 'col11', 'col12', 'col13', 'col14']; $count = count($rows); foreach ($rows as $key => $row) { $insert[] = array_combine($arrKeys, $row); // Cứ mỗi 1000 rows thì insert db 1 lần if ($key%1000 == 999 || $key == $count - 1) { DB::table('imports')->insert($insert); $insert = []; } } // Done $this->showTime(); } public function showTime() { $t = microtime(true); $micro = sprintf("%06d",($t - floor($t)) * 1000000); $d = new DateTime( date('Y-m-d H:i:s.'.$micro, $t) ); $this->error('Time: ' . $d->format("Y-m-d H:i:s.u")); return $d; } }
Kết quả
// Thời gian bắt đầu Time: 2018-08-27 15:04:45.989660 // Load xong file Time: 2018-08-27 15:05:10.979576 // Nạp rows Time: 2018-08-27 15:05:28.178913 // Done Time: 2018-08-27 15:05:37.860093
Đọc xong file 12MB, 100.000 rows, 14 cột mất 25 giây.
Insert 100.000 rows vào DB hết gần 10s
Source code cho anh em nào cần: https://github.com/nguyentranchung/excel-import-100000-record-sample
Vậy thôi