07/09/2018, 17:50

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 

0