Trong quá trình thực hiện dự án cho công ty, một trong những yêu cầu đặt ra là import dữ liệu từ file CSV (chứa dữ liệu từ hệ thống cũ) vào cơ sở dữ liệu MySQL của hệ thống mới.

Do sự thay đổi cấu trúc dữ liệu trong hệ thống mới, việc xử lý dữ liệu trước khi import vào trở thành bước quan trọng.

Tuy nhiên, thách thức đặt ra là kích thước lớn của dữ liệu từ hệ thống cũ, yêu cầu quá trình import phải diễn ra một cách nhanh chóng.

Sau quá trình nghiên cứu và thảo luận với đồng đội trong công ty, mình đã đề xuất một phương pháp xử lý hiệu quả như sau:

Trong bài viết này, mình sử dụng Laravel Framework phiên bản 10.

Tạo Command trong Laravel

php artisan make:command ImportCSV

Đọc và Xử lý Dữ liệu từ File CSV

 Đọc dữ liệu từ file CSV bằng phương pháp Chunk.

Sau đó sẽ xử lý dữ liệu cũ để tương thích với hệ thống mới và ghi kết quả xử lý thành CSV mới.

public function handle()
{
    $filename     = storage_path('transfers/data.csv');
    $filetransfer = storage_path('transfers/data-transfer.csv');
    $chunk_size   = 10000;
    
    if (($handle = fopen($filename, "r")) !== FALSE) {
        $header    = fgetcsv($handle);
        $now       = now();
        $row_count = 0;
        $chunk     = [];
        $transfer  = fopen($filetransfer, 'w');
        
        while (($row = fgetcsv($handle)) !== FALSE) {
            $row_count++;
            $chunk[] = $row;
            
            if ($row_count >= $chunk_size) {
                $this->_writeCSV($header, $chunk, $now, $transfer);
                $chunk     = [];
                $row_count = 0;
            }
        }
        
        if (!empty($chunk)) {
            $this->_writeCSV($header, $chunk, $now, $transfer);
        }
        
        fclose($handle);
        fclose($transfer);
        $this->_loadDataLocalInFile($filetransfer);
    } else {
        echo "Cannot open file $filename.";
    }
}

private function _writeCSV($header, $chunk, $now, $transfer)
{
    foreach ($chunk as $row) {
        fputcsv($transfer, [
            # Xử lý dữ liệu cũ và ghi thành file CSV
        ]);
    }
}

Import Dữ liệu vào Cơ sở Dữ liệu mới

Mình sẽ sử dụng LOAD DATA LOCAL INFILE đây một câu lệnh trong MySQL được sử dụng để nạp dữ liệu từ một file local vào một bảng trong cơ sở dữ liệu.

Đây là một cách hiệu quả để import dữ liệu từ các tệp CSV hoặc văn bản vào MySQL mà không cần phải truyền qua ứng dụng trung gian.

private function _loadDataLocalInFile($file)
{
    $table = 'name_table';
    $query = "
        LOAD DATA LOCAL INFILE '{$file}'
        INTO TABLE {$table}
        FIELDS TERMINATED BY ','
        ENCLOSED BY '\"'
        LINES TERMINATED BY '\n'
        (table_columns)
    ";
    DB::connection()->getPdo()->exec($query);
}

Cấu hình Laravel cho LOAD DATA LOCAL INFILE

Để thực hiện được lệnh LOAD DATA LOCAL INFILE trong Laravel.

Cần phải thêm option MYSQL_ATTR_LOCAL_INFILE vào MySQL trong config/database.php

'mysql' => [
    ...
    'options' => extension_loaded('pdo_mysql') ? array_filter([
        ...
        PDO::MYSQL_ATTR_LOCAL_INFILE => true,
    ]) : [],
],

Hy vọng rằng, với cách tiếp cận này, quá trình import dữ liệu sẽ diễn ra một cách hiệu quả và nhanh chóng, đồng thời đảm bảo tính chính xác và sự đồng bộ giữa hệ thống cũ và mới trong dự án của bạn.

CÓ THỂ BẠN QUAN TÂM

Laravel Queues and Jobs

Laravel Queues and Jobs

Các công ty có thẻ gặp khó khăn trong việc quản lý các dịch vụ hoặc ứng dụng của họ. Ví dụ, các công ty các thực hiện gửi email cho hàng triệu người dùng hoặc thực hiện sao lưu dữ liệu. Tất cả các hoạ...

Eloquent Methods: whereDoesntHaveRelation and whereMorphDoesntHaveRelation

Eloquent Methods: whereDoesntHaveRelation and whereMorphDoesntHaveRelation

New Laravel 11.37: Eloquent Methods Laravel cung cấp cho chúng ta khả năng xây dựng các truy vấn dữ liệu mạnh mẽ với Eloquent ORM, giúp chúng ta có thể xử lý các truy vấn cơ sở dữ liệu phức tạp một...

Laravel UI Password Reset Expired

Laravel UI Password Reset Expired

Trong thư viện laravel/ui, thì chức năng password reset dù cho token có hết hạn thì vẫn có truy cập vào trang password reset, đến khi bạn submit form thì mới thông báo là token đã hết hạn. Nhưng có mộ...

Laravel customize your API Versioning Route File

Laravel customize your API Versioning Route File

Trong khuôn khổ của Laravel, các route của api được tách thành một file duy nhất, đó là file api.php nằm trong thư mục routes . Nếu chúng ta muốn thêm version vào route api thì chúng ta sẽ làm như...

Laravel Custom Eloquent Casts

Laravel Custom Eloquent Casts

Trước đây, chúng ta bị giới hạn cast mặc định do Laravel cung cấp. Mặc dù, có một số gói thư viện có thể  giúp chúng ta custom được nhưng chúng có một nhược điểm lớn. Bởi vì, chúng ghi đề phương thức...

Generate PDF with Header and Footer on every page in Laravel

Generate PDF with Header and Footer on every page in Laravel

Hôm nay, trong bài viết này mình sẽ chia sẻ với các bạn cách dompdf mà header và footer sẽ được hiển thị ở tất cả các trang. Đây cũng là một vấn đề khá phổ biến, khi chúng ta phát triển các tính năng...

Send Slack Notifications In Laravel

Send Slack Notifications In Laravel

Slack là gì? Slack là một công cụ giao tiếp tại nơi làm việc, "một nơi duy nhất cho các tin nhắn, công cụ và file." Điều này có nghĩa là Slack là một hệ thống nhắn tin tức thì với nhiều plug-in cho...

Integrating elFinder into TinyMCE 6 in Laravel

Integrating elFinder into TinyMCE 6 in Laravel

TinyMCE TinyMCE là một trình soạn thảo WYSIWYG được xây dựng trên nền tảng Javascript, được phát triển dưới dạng mã nguồn mở theo giấy phép MIT bởi Tiny Technologies Inc. TinyMCE cho phép người d...

Laravel Custom Rules

Laravel Custom Rules

Trong quá trình phát triển website Laravel, mình cảm thấy hệ thống Validation của Laravel rất tuyệt vời, nó cung cấp đã cung cấp cho chúng ta một bộ quy tắc kiểm tra dữ liệu, mà trong các trường hợp b...

ManhDanBlogs